feat: allow embedded experience to open register page for authenticated users (#945)
VAN-1482
This commit is contained in:
committed by
GitHub
parent
2a2c5abc81
commit
d41c06b1fd
@@ -19,7 +19,7 @@ const RedirectLogistration = (props) => {
|
||||
redirectToRecommendationsPage,
|
||||
educationLevel,
|
||||
userId,
|
||||
isRegistrationEmbedded,
|
||||
registrationEmbedded,
|
||||
} = props;
|
||||
let finalRedirectUrl = '';
|
||||
|
||||
@@ -39,7 +39,7 @@ const RedirectLogistration = (props) => {
|
||||
// TODO: Do we still need this cookie?
|
||||
setCookie('van-504-returning-user', true);
|
||||
|
||||
if (isRegistrationEmbedded) {
|
||||
if (registrationEmbedded) {
|
||||
window.parent.postMessage({ action: REDIRECT, redirectUrl: `${window.location.origin}${AUTHN_PROGRESSIVE_PROFILING}` }, DISCOVER_URL);
|
||||
return null;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ RedirectLogistration.defaultProps = {
|
||||
optionalFields: {},
|
||||
redirectToRecommendationsPage: false,
|
||||
userId: null,
|
||||
isRegistrationEmbedded: false,
|
||||
registrationEmbedded: false,
|
||||
};
|
||||
|
||||
RedirectLogistration.propTypes = {
|
||||
@@ -99,7 +99,7 @@ RedirectLogistration.propTypes = {
|
||||
optionalFields: PropTypes.shape({}),
|
||||
redirectToRecommendationsPage: PropTypes.bool,
|
||||
userId: PropTypes.number,
|
||||
isRegistrationEmbedded: PropTypes.bool,
|
||||
registrationEmbedded: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default RedirectLogistration;
|
||||
|
||||
@@ -2,9 +2,13 @@ import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Route } from 'react-router-dom';
|
||||
|
||||
import { DEFAULT_REDIRECT_URL } from '../data/constants';
|
||||
import {
|
||||
DEFAULT_REDIRECT_URL, REGISTER_PAGE,
|
||||
} from '../data/constants';
|
||||
import { isRegistrationEmbedded } from '../data/utils/dataUtils';
|
||||
|
||||
/**
|
||||
* This wrapper redirects the requester to our default redirect url if they are
|
||||
@@ -13,13 +17,20 @@ import { DEFAULT_REDIRECT_URL } from '../data/constants';
|
||||
const UnAuthOnlyRoute = (props) => {
|
||||
const [authUser, setAuthUser] = useState({});
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
const registrationEmbedded = isRegistrationEmbedded() && props.path === REGISTER_PAGE;
|
||||
|
||||
useEffect(() => {
|
||||
if (registrationEmbedded) { return; }
|
||||
fetchAuthenticatedUser({ forceRefresh: !!getAuthenticatedUser() }).then((authenticatedUser) => {
|
||||
setAuthUser(authenticatedUser);
|
||||
setIsReady(true);
|
||||
});
|
||||
}, []);
|
||||
}, [registrationEmbedded]);
|
||||
|
||||
// Show registration page for embedded experience even if the user is authenticated
|
||||
if (registrationEmbedded) {
|
||||
return <Route {...props} />;
|
||||
}
|
||||
|
||||
if (isReady) {
|
||||
if (authUser && authUser.username) {
|
||||
@@ -33,4 +44,8 @@ const UnAuthOnlyRoute = (props) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
UnAuthOnlyRoute.propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default UnAuthOnlyRoute;
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
/* eslint-disable react/function-component-definition */
|
||||
import React from 'react';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { mount } from 'enzyme';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import { UnAuthOnlyRoute } from '..';
|
||||
import { LOGIN_PAGE } from '../../data/constants';
|
||||
import { REGISTER_PAGE } from '../../data/constants';
|
||||
|
||||
import { MemoryRouter, BrowserRouter as Router, Switch } from 'react-router-dom';
|
||||
|
||||
@@ -26,7 +27,7 @@ const TestApp = () => (
|
||||
<Router>
|
||||
<div>
|
||||
<Switch>
|
||||
<UnAuthOnlyRoute path={LOGIN_PAGE} render={() => (<span>Login Page</span>)} />
|
||||
<UnAuthOnlyRoute path={REGISTER_PAGE} render={() => (<span>Register Page</span>)} />
|
||||
</Switch>
|
||||
</div>
|
||||
</Router>
|
||||
@@ -34,7 +35,7 @@ const TestApp = () => (
|
||||
|
||||
describe('UnAuthOnlyRoute', () => {
|
||||
const routerWrapper = () => (
|
||||
<MemoryRouter initialEntries={[LOGIN_PAGE]}>
|
||||
<MemoryRouter initialEntries={[REGISTER_PAGE]}>
|
||||
<TestApp />
|
||||
</MemoryRouter>
|
||||
);
|
||||
@@ -69,4 +70,44 @@ describe('UnAuthOnlyRoute', () => {
|
||||
|
||||
expect(fetchAuthenticatedUser).toBeCalledWith({ forceRefresh: false });
|
||||
});
|
||||
|
||||
it('should not route to register page for authenticated users with non-embedded/normal experience', async () => {
|
||||
const user = {
|
||||
username: 'gonzo',
|
||||
other: 'data',
|
||||
};
|
||||
|
||||
getAuthenticatedUser.mockReturnValue(user);
|
||||
fetchAuthenticatedUser.mockReturnValueOnce(Promise.resolve(user));
|
||||
|
||||
let registerPage = null;
|
||||
|
||||
await act(async () => {
|
||||
registerPage = await mount(routerWrapper());
|
||||
});
|
||||
|
||||
expect(registerPage.find('span').exists()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should route to register page for authenticated users with embedded experience', async () => {
|
||||
const user = {
|
||||
username: 'gonzo',
|
||||
other: 'data',
|
||||
};
|
||||
|
||||
delete window.location;
|
||||
window.location = { href: getConfig().BASE_URL.concat(REGISTER_PAGE), search: '?variant=embedded' };
|
||||
|
||||
getAuthenticatedUser.mockReturnValue(user);
|
||||
fetchAuthenticatedUser.mockReturnValueOnce(Promise.resolve(user));
|
||||
|
||||
let registerPage = null;
|
||||
|
||||
await act(async () => {
|
||||
registerPage = await mount(routerWrapper());
|
||||
});
|
||||
|
||||
expect(registerPage.find('span').exists()).toBeTruthy();
|
||||
expect(registerPage.find('span').text()).toBe('Register Page');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Utility functions
|
||||
import * as QueryString from 'query-string';
|
||||
|
||||
import { AUTH_PARAMS } from '../constants';
|
||||
import { AUTH_PARAMS, EMBEDDED } from '../constants';
|
||||
|
||||
export const getTpaProvider = (tpaHintProvider, primaryProviders, secondaryProviders) => {
|
||||
let tpaProvider = null;
|
||||
@@ -76,3 +76,8 @@ export const windowScrollTo = (options) => {
|
||||
|
||||
return window.scrollTo(options.top, options.left);
|
||||
};
|
||||
|
||||
export const isRegistrationEmbedded = () => {
|
||||
const queryParams = getAllPossibleQueryParams();
|
||||
return queryParams?.variant === EMBEDDED;
|
||||
};
|
||||
|
||||
@@ -20,10 +20,11 @@ import {
|
||||
tpaProvidersSelector,
|
||||
} from '../common-components/data/selectors';
|
||||
import messages from '../common-components/messages';
|
||||
import { EMBEDDED, LOGIN_PAGE, REGISTER_PAGE } from '../data/constants';
|
||||
import { LOGIN_PAGE, REGISTER_PAGE } from '../data/constants';
|
||||
import {
|
||||
getAllPossibleQueryParams, getTpaHint, getTpaProvider, updatePathWithQueryParams,
|
||||
getTpaHint, getTpaProvider, updatePathWithQueryParams,
|
||||
} from '../data/utils';
|
||||
import { isRegistrationEmbedded } from '../data/utils/dataUtils';
|
||||
import { LoginPage } from '../login';
|
||||
import { RegistrationPage } from '../register';
|
||||
import { backupRegistrationForm } from '../register/data/actions';
|
||||
@@ -38,7 +39,7 @@ const Logistration = (props) => {
|
||||
const [institutionLogin, setInstitutionLogin] = useState(false);
|
||||
const [key, setKey] = useState('');
|
||||
const disablePublicAccountCreation = getConfig().ALLOW_PUBLIC_ACCOUNT_CREATION === false;
|
||||
const isRegistrationEmbedded = getAllPossibleQueryParams()?.variant === EMBEDDED && selectedPage === REGISTER_PAGE;
|
||||
const registrationEmbedded = isRegistrationEmbedded() && selectedPage === REGISTER_PAGE;
|
||||
|
||||
useEffect(() => {
|
||||
const authService = getAuthService();
|
||||
@@ -109,7 +110,7 @@ const Logistration = (props) => {
|
||||
<Tab title={tabTitle} eventKey={selectedPage === LOGIN_PAGE ? LOGIN_PAGE : REGISTER_PAGE} />
|
||||
</Tabs>
|
||||
)
|
||||
: (!isRegistrationEmbedded && !isValidTpaHint() && (
|
||||
: (!registrationEmbedded && !isValidTpaHint() && (
|
||||
<Tabs defaultActiveKey={selectedPage} id="controlled-tab" onSelect={handleOnSelect}>
|
||||
<Tab title={formatMessage(messages['logistration.register'])} eventKey={REGISTER_PAGE} />
|
||||
<Tab title={formatMessage(messages['logistration.sign.in'])} eventKey={LOGIN_PAGE} />
|
||||
@@ -133,7 +134,7 @@ const Logistration = (props) => {
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
isRegistrationEmbedded ? (
|
||||
registrationEmbedded ? (
|
||||
renderLogistrationTabs()
|
||||
) : (
|
||||
<BaseComponent>
|
||||
|
||||
@@ -48,11 +48,12 @@ import {
|
||||
import EnterpriseSSO from '../common-components/EnterpriseSSO';
|
||||
import {
|
||||
COMPLETE_STATE, DEFAULT_STATE,
|
||||
EMBEDDED, INVALID_NAME_REGEX, LETTER_REGEX, NUMBER_REGEX, PENDING_STATE, REGISTER_PAGE, VALID_EMAIL_REGEX,
|
||||
INVALID_NAME_REGEX, LETTER_REGEX, NUMBER_REGEX, PENDING_STATE, REGISTER_PAGE, VALID_EMAIL_REGEX,
|
||||
} from '../data/constants';
|
||||
import {
|
||||
getAllPossibleQueryParams, getTpaHint, getTpaProvider, setCookie,
|
||||
} from '../data/utils';
|
||||
import { isRegistrationEmbedded } from '../data/utils/dataUtils';
|
||||
|
||||
const emailRegex = new RegExp(VALID_EMAIL_REGEX, 'i');
|
||||
const urlRegex = new RegExp(INVALID_NAME_REGEX);
|
||||
@@ -87,7 +88,7 @@ const RegistrationPage = (props) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const countryList = useMemo(() => getCountryList(getLocale()), []);
|
||||
const queryParams = useMemo(() => getAllPossibleQueryParams(), []);
|
||||
const isRegistrationEmbedded = queryParams?.variant === EMBEDDED;
|
||||
const registrationEmbedded = isRegistrationEmbedded();
|
||||
const tpaHint = useMemo(() => getTpaHint(), []);
|
||||
const flags = {
|
||||
showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS,
|
||||
@@ -520,7 +521,7 @@ const RegistrationPage = (props) => {
|
||||
redirectUrl={registrationResult.redirectUrl}
|
||||
finishAuthUrl={finishAuthUrl}
|
||||
optionalFields={optionalFields}
|
||||
isRegistrationEmbedded={isRegistrationEmbedded}
|
||||
registrationEmbedded={registrationEmbedded}
|
||||
redirectToProgressiveProfilingPage={
|
||||
getConfig().ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN && Object.keys(optionalFields).includes('fields')
|
||||
}
|
||||
@@ -533,7 +534,7 @@ const RegistrationPage = (props) => {
|
||||
<div
|
||||
className={classNames(
|
||||
'mw-xs mt-3',
|
||||
{ 'w-100 m-auto': isRegistrationEmbedded },
|
||||
{ 'w-100 m-auto': registrationEmbedded },
|
||||
)}
|
||||
>
|
||||
<ThirdPartyAuthAlert
|
||||
@@ -619,7 +620,7 @@ const RegistrationPage = (props) => {
|
||||
onClick={handleSubmit}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
/>
|
||||
{!isRegistrationEmbedded && (
|
||||
{!registrationEmbedded && (
|
||||
<ThirdPartyAuth
|
||||
currentProvider={currentProvider}
|
||||
providers={providers}
|
||||
|
||||
Reference in New Issue
Block a user