mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-19 18:18:27 -05:00
feat(client): redirect from /settings + /update-email after sign out (#64405)
This commit is contained in:
committed by
GitHub
parent
c0b9aa2cb0
commit
a67abd3fbc
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Modal, Spacer } from '@freecodecamp/ui';
|
||||
|
||||
import { hardGoTo as navigate, closeSignoutModal } from '../../redux/actions';
|
||||
import { closeSignoutModal } from '../../redux/actions';
|
||||
import { isSignoutModalOpenSelector } from '../../redux/selectors';
|
||||
import { apiLocation } from '../../../config/env.json';
|
||||
import callGA from '../../analytics/call-ga';
|
||||
@@ -20,20 +20,31 @@ const mapStateToProps = createSelector(
|
||||
const mapDispatchToProps = (dispatch: Dispatch<AnyAction>) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
navigate,
|
||||
closeSignoutModal
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
type SignoutModalProps = {
|
||||
navigate: (path: string) => void;
|
||||
closeSignoutModal: () => void;
|
||||
show: boolean;
|
||||
};
|
||||
|
||||
export const pathAfterSignout = (currentPath: string): string => {
|
||||
// These pages try to sign in the user automatically if they are signed out,
|
||||
// so, to respect the user's intention to sign out, we redirect them to /learn
|
||||
// instead.
|
||||
const redirectedPaths = ['/settings', '/update-email'];
|
||||
const allPaths = [
|
||||
...redirectedPaths,
|
||||
...redirectedPaths.map(path => `${path}/`)
|
||||
];
|
||||
|
||||
return allPaths.some(path => currentPath === path) ? '/learn' : currentPath;
|
||||
};
|
||||
|
||||
function SignoutModal(props: SignoutModalProps): JSX.Element {
|
||||
const { show, closeSignoutModal, navigate } = props;
|
||||
const { show, closeSignoutModal } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleModalHide = () => {
|
||||
@@ -43,7 +54,15 @@ function SignoutModal(props: SignoutModalProps): JSX.Element {
|
||||
const handleSignout = () => {
|
||||
closeSignoutModal();
|
||||
callGA({ event: 'sign_out', user_id: undefined });
|
||||
navigate(`${apiLocation}/signout`);
|
||||
const redirect = () => {
|
||||
window.location.pathname = pathAfterSignout(window.location.pathname);
|
||||
};
|
||||
void fetch(`${apiLocation}/signout`, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(redirect)
|
||||
.catch(redirect);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
31
client/src/components/signout-modal/signout-modal.test.ts
Normal file
31
client/src/components/signout-modal/signout-modal.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
import { pathAfterSignout } from '.';
|
||||
|
||||
describe('pathAfterSignout', () => {
|
||||
it('should default to the supplied path', () => {
|
||||
const unexceptionalPath = 'a/normal/path/';
|
||||
expect(pathAfterSignout(unexceptionalPath)).toBe(unexceptionalPath);
|
||||
});
|
||||
|
||||
it('should redirect paths that automatically sign in back to /learn', () => {
|
||||
const pathsThatAttemptToSignIn = ['/settings', '/update-email'];
|
||||
const newPaths = pathsThatAttemptToSignIn.map(pathAfterSignout);
|
||||
|
||||
expect(newPaths).toEqual(['/learn', '/learn']);
|
||||
});
|
||||
|
||||
it('should redirect paths with trailing slashes', () => {
|
||||
const pathsThatAttemptToSignIn = ['/settings/', '/update-email/'];
|
||||
const newPaths = pathsThatAttemptToSignIn.map(pathAfterSignout);
|
||||
|
||||
expect(newPaths).toEqual(['/learn', '/learn']);
|
||||
});
|
||||
|
||||
it('should only redirect exact matches', () => {
|
||||
const similarPaths = ['/settingss', '/update-emails/', '/settings/2'];
|
||||
const newPaths = similarPaths.map(pathAfterSignout);
|
||||
|
||||
expect(newPaths).toEqual(similarPaths);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user