Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/common-components/EmbeddedRegistrationRoute.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import { Navigate } from 'react-router-dom';

import { PAGE_NOT_FOUND } from '../data/constants';
import { notFoundPath } from '../constants';
import { isHostAvailableInQueryParams } from '../data/utils';

/**
Expand All @@ -16,7 +16,7 @@ const EmbeddedRegistrationRoute = ({ children }) => {
return children;
}

return <Navigate to={PAGE_NOT_FOUND} replace />;
return <Navigate to={`../${notFoundPath}`} replace />;
Comment thread
holaontiveros marked this conversation as resolved.
};

EmbeddedRegistrationRoute.propTypes = {
Expand Down
9 changes: 6 additions & 3 deletions src/common-components/EnterpriseSSO.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { useAppConfig, getSiteConfig, getUrlByRouteRole, useIntl } from '@openedx/frontend-base';
import {
Button, Form,
Icon,
} from '@openedx/paragon';
import { Login } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
import { useNavigate } from 'react-router-dom';

import { LOGIN_PAGE, SUPPORTED_ICON_CLASSES } from '../data/constants';
import { loginRole } from '../constants';
import { SUPPORTED_ICON_CLASSES } from '../data/constants';
import messages from './messages';

/**
* This component renders the Single sign-on (SSO) button only for the tpa provider passed
* */
const EnterpriseSSO = (props) => {
const { formatMessage } = useIntl();
const navigate = useNavigate();
const tpaProvider = props.provider;
const hideRegistrationLink = useAppConfig().ALLOW_PUBLIC_ACCOUNT_CREATION === false
|| useAppConfig().SHOW_REGISTRATION_LINKS === false;
Expand All @@ -26,7 +29,7 @@ const EnterpriseSSO = (props) => {

const handleClick = (e) => {
e.preventDefault();
window.location.href = LOGIN_PAGE;
navigate(getUrlByRouteRole(loginRole));
};

if (tpaProvider) {
Expand Down
12 changes: 7 additions & 5 deletions src/common-components/RedirectLogistration.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useAppConfig, getSiteConfig } from '@openedx/frontend-base';
import { useAppConfig, getSiteConfig, getUrlByRouteRole } from '@openedx/frontend-base';
import PropTypes from 'prop-types';
import { Navigate } from 'react-router-dom';

import {
AUTHN_PROGRESSIVE_PROFILING, REDIRECT,
} from '../data/constants';
import { welcomeRole } from '../constants';
import { REDIRECT } from '../data/constants';
import { setCookie } from '../data/utils';

const RedirectLogistration = (props) => {
Expand Down Expand Up @@ -48,7 +47,7 @@ const RedirectLogistration = (props) => {
const registrationResult = { redirectUrl: finalRedirectUrl, success };
return (
<Navigate
to={AUTHN_PROGRESSIVE_PROFILING}
to={getUrlByRouteRole(welcomeRole)}
state={{
registrationResult,
optionalFields,
Expand All @@ -59,6 +58,9 @@ const RedirectLogistration = (props) => {
);
}

if (finalRedirectUrl.startsWith('/')) {
return <Navigate to={finalRedirectUrl} replace />;
}
window.location.href = finalRedirectUrl;
}

Expand Down
9 changes: 5 additions & 4 deletions src/common-components/SocialAuthProviders.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Icon } from '@openedx/paragon';
import { Login } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';

import { LOGIN_PAGE, SUPPORTED_ICON_CLASSES } from '../data/constants';
import { loginPath } from '../constants';
import { SUPPORTED_ICON_CLASSES } from '../data/constants';
import messages from './messages';

const SocialAuthProviders = (props) => {
Expand All @@ -24,7 +25,7 @@ const SocialAuthProviders = (props) => {
key={provider.id}
type="button"
className={`btn-social btn-${provider.id} ${index % 2 === 0 ? 'mr-3' : ''}`}
data-provider-url={referrer === LOGIN_PAGE ? provider.loginUrl : provider.registerUrl}
data-provider-url={referrer === loginPath ? provider.loginUrl : provider.registerUrl}
onClick={handleSubmit}
>
{provider.iconImage ? (
Expand All @@ -43,7 +44,7 @@ const SocialAuthProviders = (props) => {
)}
<span id="provider-name" className="notranslate mr-auto pl-2" aria-hidden="true">{provider.name}</span>
<span className="sr-only">
{referrer === LOGIN_PAGE
{referrer === loginPath
? formatMessage(messages['sso.sign.in.with'], { providerName: provider.name })
: formatMessage(messages['sso.create.account.using'], { providerName: provider.name })}
</span>
Expand All @@ -55,7 +56,7 @@ const SocialAuthProviders = (props) => {
};

SocialAuthProviders.defaultProps = {
referrer: LOGIN_PAGE,
referrer: loginPath,
socialAuthProviders: [],
};

Expand Down
7 changes: 3 additions & 4 deletions src/common-components/ThirdPartyAuth.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import classNames from 'classnames';
import PropTypes from 'prop-types';
import Skeleton from 'react-loading-skeleton';

import {
ENTERPRISE_LOGIN_URL, LOGIN_PAGE, PENDING_STATE, REGISTER_PAGE,
} from '../data/constants';
import { loginPath, registerPath } from '../constants';
import { ENTERPRISE_LOGIN_URL, PENDING_STATE } from '../data/constants';
import messages from './messages';

import {
Expand Down Expand Up @@ -75,7 +74,7 @@ const ThirdPartyAuth = (props) => {
<div className="row m-0">
<SocialAuthProviders
socialAuthProviders={providers}
referrer={isLoginPage ? LOGIN_PAGE : REGISTER_PAGE}
referrer={isLoginPage ? loginPath : registerPath}
/>
</div>
)}
Expand Down
12 changes: 6 additions & 6 deletions src/common-components/ThirdPartyAuthAlert.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Alert } from '@openedx/paragon';
import PropTypes from 'prop-types';

import { LOGIN_PAGE, REGISTER_PAGE } from '../data/constants';
import { loginPath, registerPath } from '../constants';
import messages from './messages';

const ThirdPartyAuthAlert = (props) => {
Expand All @@ -11,7 +11,7 @@ const ThirdPartyAuthAlert = (props) => {
const platformName = getSiteConfig().siteName;
let message;

if (referrer === LOGIN_PAGE) {
if (referrer === loginPath) {
message = formatMessage(messages['login.third.party.auth.account.not.linked'], { currentProvider, platformName });
} else {
message = formatMessage(messages['register.third.party.auth.account.not.linked'], { currentProvider, platformName });
Expand All @@ -23,13 +23,13 @@ const ThirdPartyAuthAlert = (props) => {

return (
<>
<Alert id="tpa-alert" className={referrer === REGISTER_PAGE ? 'alert-success mt-n2 mb-5' : 'alert-warning mt-n2 mb-5'}>
{referrer === REGISTER_PAGE ? (
<Alert id="tpa-alert" className={referrer === registerPath ? 'alert-success mt-n2 mb-5' : 'alert-warning mt-n2 mb-5'}>
{referrer === registerPath ? (
<Alert.Heading>{formatMessage(messages['tpa.alert.heading'])}</Alert.Heading>
) : null}
<p>{message}</p>
</Alert>
{referrer === REGISTER_PAGE ? (
{referrer === registerPath ? (
<h4 className="mt-4 mb-4">{formatMessage(messages['registration.using.tpa.form.heading'])}</h4>
) : null}
</>
Expand All @@ -38,7 +38,7 @@ const ThirdPartyAuthAlert = (props) => {

ThirdPartyAuthAlert.defaultProps = {
currentProvider: '',
referrer: LOGIN_PAGE,
referrer: loginPath,
};

ThirdPartyAuthAlert.propTypes = {
Expand Down
10 changes: 4 additions & 6 deletions src/common-components/UnAuthOnlyRoute.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useEffect, useState } from 'react';

import { fetchAuthenticatedUser, getAuthenticatedUser, getSiteConfig } from '@openedx/frontend-base';
import { fetchAuthenticatedUser, getAuthenticatedUser, getUrlByRouteRole } from '@openedx/frontend-base';
import PropTypes from 'prop-types';
import { Navigate } from 'react-router-dom';

import {
DEFAULT_REDIRECT_URL,
} from '../data/constants';
import { dashboardRole } from '../constants';

/**
* This wrapper redirects the requester to our default redirect url if they are
Expand All @@ -24,8 +23,7 @@ const UnAuthOnlyRoute = ({ children }) => {

if (isReady) {
if (authUser && authUser.username) {
global.location.href = getSiteConfig().lmsBaseUrl.concat(DEFAULT_REDIRECT_URL);
return null;
return <Navigate to={getUrlByRouteRole(dashboardRole) || '/'} replace />;
}

return children;
Expand Down
73 changes: 26 additions & 47 deletions src/common-components/tests/EmbeddedRegistrationRoute.test.jsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,27 @@
/* eslint-disable import/no-import-module-exports */
/* eslint-disable react/function-component-definition */

import { getSiteConfig } from '@openedx/frontend-base';
import { render } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { render, waitFor } from '@testing-library/react';
import {
MemoryRouter, Route, BrowserRouter as Router, Routes,
MemoryRouter, Navigate, Outlet, Route, Routes,
} from 'react-router-dom';

import { PAGE_NOT_FOUND, REGISTER_EMBEDDED_PAGE } from '../../data/constants';
import { notFoundPath, registerEmbeddedPath } from '../../constants';
import EmbeddedRegistrationRoute from '../EmbeddedRegistrationRoute';

const RRD = require('react-router-dom');
// Just render plain div with its children
// eslint-disable-next-line react/prop-types
RRD.BrowserRouter = ({ children }) => <div>{children}</div>;
module.exports = RRD;

const TestApp = () => (
<Router>
<div>
<Routes>
<Route
path={REGISTER_EMBEDDED_PAGE}
element={<EmbeddedRegistrationRoute><span>Embedded Register Page</span></EmbeddedRegistrationRoute>}
/>
<Route
path={PAGE_NOT_FOUND}
element={<span>Page not found</span>}
/>
</Routes>
</div>
</Router>
);

describe('EmbeddedRegistrationRoute', () => {
const routerWrapper = () => (
<MemoryRouter initialEntries={[REGISTER_EMBEDDED_PAGE]}>
<TestApp />
<MemoryRouter initialEntries={[`/authn/${registerEmbeddedPath}`]}>
<Routes>
<Route path="/authn" element={<Outlet />}>
<Route
path={registerEmbeddedPath}
element={<EmbeddedRegistrationRoute><span>Embedded Register Page</span></EmbeddedRegistrationRoute>}
/>
<Route
path={notFoundPath}
element={<span>Page not found</span>}
/>
</Route>
</Routes>
</MemoryRouter>
);

Expand All @@ -46,30 +30,25 @@ describe('EmbeddedRegistrationRoute', () => {
});

it('should not render embedded register page if host query param is not available in the url', async () => {
let embeddedRegistrationPage = null;
await act(async () => {
const { container } = await render(routerWrapper());
embeddedRegistrationPage = container;
});
const { container } = render(routerWrapper());

const renderedPage = embeddedRegistrationPage.querySelector('span');
expect(renderedPage.textContent).toBe('Page not found');
await waitFor(() => {
const renderedPage = container.querySelector('span');
expect(renderedPage).not.toBeNull();
expect(renderedPage.textContent).toBe('Page not found');
});
});

it('should render embedded register page if host query param is available in the url (embedded)', async () => {
it('should render embedded register page if host query param is available in the url (embedded)', () => {
delete window.location;
window.location = {
href: getSiteConfig().baseUrl.concat(REGISTER_EMBEDDED_PAGE),
href: getSiteConfig().baseUrl.concat('/', registerEmbeddedPath),
search: '?host=http://localhost/host-websit',
};

let embeddedRegistrationPage = null;
await act(async () => {
const { container } = await render(routerWrapper());
embeddedRegistrationPage = container;
});
const { container } = render(routerWrapper());

const renderedPage = embeddedRegistrationPage.querySelector('span');
const renderedPage = container.querySelector('span');
expect(renderedPage).toBeTruthy();
expect(renderedPage.textContent).toBe('Embedded Register Page');
});
Expand Down
5 changes: 3 additions & 2 deletions src/common-components/tests/ThirdPartyAuthAlert.test.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IntlProvider } from '@openedx/frontend-base';
import renderer from 'react-test-renderer';

import { PENDING_STATE, REGISTER_PAGE } from '../../data/constants';
import { registerPath } from '../../constants';
import { PENDING_STATE } from '../../data/constants';
Comment thread
holaontiveros marked this conversation as resolved.
import ThirdPartyAuthAlert from '../ThirdPartyAuthAlert';

describe('ThirdPartyAuthAlert', () => {
Expand All @@ -26,7 +27,7 @@ describe('ThirdPartyAuthAlert', () => {
it('should match register page third party auth alert message snapshot', () => {
props = {
...props,
referrer: REGISTER_PAGE,
referrer: registerPath,
};

const tree = renderer.create(
Expand Down
7 changes: 4 additions & 3 deletions src/common-components/tests/UnAuthOnlyRoute.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import {
} from 'react-router-dom';

import { UnAuthOnlyRoute } from '..';
import { REGISTER_PAGE } from '../../data/constants';
import { registerPath } from '../../constants';

jest.mock('@openedx/frontend-base', () => ({
...jest.requireActual('@openedx/frontend-base'),
getAuthenticatedUser: jest.fn(),
fetchAuthenticatedUser: jest.fn(),
getUrlByRouteRole: jest.fn(() => '/dashboard'),
}));

const RRD = require('react-router-dom');
Expand All @@ -27,15 +28,15 @@ const TestApp = () => (
<Router>
<div>
<Routes>
<Route path={REGISTER_PAGE} element={<UnAuthOnlyRoute><span>Register Page</span></UnAuthOnlyRoute>} />
<Route path={`/${registerPath}`} element={<UnAuthOnlyRoute><span>Register Page</span></UnAuthOnlyRoute>} />
</Routes>
</div>
</Router>
);

describe('UnAuthOnlyRoute', () => {
const routerWrapper = () => (
<MemoryRouter initialEntries={[REGISTER_PAGE]}>
<MemoryRouter initialEntries={[`/${registerPath}`]}>
<TestApp />
</MemoryRouter>
);
Expand Down
17 changes: 17 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
export const appId = 'org.openedx.frontend.app.authn';

// Route roles
export const loginRole = 'org.openedx.frontend.role.login';
export const registerRole = 'org.openedx.frontend.role.register';
export const resetPasswordRole = 'org.openedx.frontend.role.resetPassword';
export const confirmPasswordRole = 'org.openedx.frontend.role.confirmPassword';
export const welcomeRole = 'org.openedx.frontend.role.welcome';
export const dashboardRole = 'org.openedx.frontend.role.dashboard';

// Route path segments
export const loginPath = 'login';
export const registerPath = 'register';
export const registerEmbeddedPath = 'register-embedded';
export const resetPath = 'reset';
export const welcomePath = 'welcome';
export const passwordResetConfirmPath = 'password_reset_confirm';
export const notFoundPath = 'notfound';
9 changes: 0 additions & 9 deletions src/data/constants.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
// URL Paths
export const LOGIN_PAGE = '/login';
export const REGISTER_PAGE = '/register';
export const REGISTER_EMBEDDED_PAGE = '/register-embedded';
export const RESET_PAGE = '/reset';
export const AUTHN_PROGRESSIVE_PROFILING = '/welcome';
export const DEFAULT_REDIRECT_URL = '/dashboard';
export const PASSWORD_RESET_CONFIRM = '/password_reset_confirm/:token/';
export const PAGE_NOT_FOUND = '/notfound';
export const ENTERPRISE_LOGIN_URL = '/enterprise/login';

// Constants
Expand Down
Loading
Loading