Skip to content

Commit

Permalink
Merge pull request #405 from auth0/with-page-auth-required-props
Browse files Browse the repository at this point in the history
[SDK-2586] Add `user` to `withPageAuthRequiredProps` CSR to match SSR
  • Loading branch information
adamjmcgrath committed Jun 1, 2021
2 parents 32e9200 + dd9c8c2 commit bba8851
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 36 deletions.
24 changes: 4 additions & 20 deletions examples/kitchen-sink-example/pages/profile.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
import React from 'react';
import { useUser, withPageAuthRequired } from '@auth0/nextjs-auth0';
import { withPageAuthRequired } from '@auth0/nextjs-auth0';

import Layout from '../components/layout';

export default withPageAuthRequired(function Profile(): React.ReactElement {
const { user, error, isLoading } = useUser();

export default withPageAuthRequired(function Profile({ user }) {
return (
<Layout>
<h1>Profile</h1>

{isLoading && <p>Loading profile...</p>}

{error && (
<>
<h4>Error</h4>
<pre>{error.message}</pre>
</>
)}

{user && (
<>
<h4>Profile</h4>
<pre data-testid="profile">{JSON.stringify(user, null, 2)}</pre>
</>
)}
<h4>Profile</h4>
<pre data-testid="profile">{JSON.stringify(user, null, 2)}</pre>
</Layout>
);
});
7 changes: 6 additions & 1 deletion src/frontend/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
export { default as ConfigProvider, ConfigProviderProps, useConfig } from './use-config';
export { default as UserProvider, UserProviderProps, UserProfile, UserContext, useUser } from './use-user';
export { default as withPageAuthRequired, WithPageAuthRequired } from './with-page-auth-required';
export {
default as withPageAuthRequired,
WithPageAuthRequired,
WithPageAuthRequiredProps,
WithPageAuthRequiredOptions
} from './with-page-auth-required';
17 changes: 12 additions & 5 deletions src/frontend/with-page-auth-required.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { ComponentType, useEffect } from 'react';

import { useConfig } from './use-config';
import { useUser } from './use-user';
import { useUser, UserProfile } from './use-user';

/**
* @ignore
Expand Down Expand Up @@ -51,6 +51,14 @@ export interface WithPageAuthRequiredOptions {
onError?: (error: Error) => JSX.Element;
}

/**
* @ignore
*/
export interface WithPageAuthRequiredProps {
user: UserProfile;
[key: string]: any;
}

/**
* ```js
* const MyProtectedPage = withPageAuthRequired(MyPage);
Expand All @@ -61,11 +69,10 @@ export interface WithPageAuthRequiredOptions {
*
* @category Client
*/
// eslint-disable-next-line @typescript-eslint/ban-types
export type WithPageAuthRequired = <P extends object>(
export type WithPageAuthRequired = <P extends WithPageAuthRequiredProps>(
Component: ComponentType<P>,
options?: WithPageAuthRequiredOptions
) => React.FC<P>;
) => React.FC<Omit<P, 'user'>>;

/**
* @ignore
Expand All @@ -91,7 +98,7 @@ const withPageAuthRequired: WithPageAuthRequired = (Component, options = {}) =>
}, [user, error, isLoading]);

if (error) return onError(error);
if (user) return <Component {...props} />;
if (user) return <Component user={user} {...(props as any)} />;

return onRedirecting();
};
Expand Down
9 changes: 6 additions & 3 deletions src/helpers/with-page-auth-required.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { GetServerSideProps, GetServerSidePropsContext, GetServerSidePropsResult
import { Claims, GetSession } from '../session';
import { assertCtx } from '../utils/assert';
import React, { ComponentType } from 'react';
import { WithPageAuthRequiredOptions as WithPageAuthRequiredCSROptions } from '../frontend/with-page-auth-required';
import {
WithPageAuthRequiredOptions as WithPageAuthRequiredCSROptions,
WithPageAuthRequiredProps
} from '../frontend/with-page-auth-required';
import { withPageAuthRequired as withPageAuthRequiredCSR } from '../frontend';

/**
Expand Down Expand Up @@ -81,7 +84,7 @@ export type WithPageAuthRequiredOptions = { getServerSideProps?: GetServerSidePr
*/
export type WithPageAuthRequired = {
(opts?: WithPageAuthRequiredOptions): PageRoute;
<P extends { [key: string]: any }>(
<P extends WithPageAuthRequiredProps>(
Component: ComponentType<P>,
options?: WithPageAuthRequiredCSROptions
): React.FC<P>;
Expand All @@ -92,7 +95,7 @@ export type WithPageAuthRequired = {
*/
export default function withPageAuthRequiredFactory(loginUrl: string, getSession: GetSession): WithPageAuthRequired {
return (
optsOrComponent: WithPageAuthRequiredOptions | ComponentType = {},
optsOrComponent: WithPageAuthRequiredOptions | ComponentType<WithPageAuthRequiredProps> = {},
csrOpts?: WithPageAuthRequiredCSROptions
): any => {
if (typeof optsOrComponent === 'function') {
Expand Down
12 changes: 9 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,21 @@ export const initAuth0: InitAuth0 = (params) => {
export const getSession: GetSession = (...args) => getInstance().getSession(...args);
export const getAccessToken: GetAccessToken = (...args) => getInstance().getAccessToken(...args);
export const withApiAuthRequired: WithApiAuthRequired = (...args) => getInstance().withApiAuthRequired(...args);
export const withPageAuthRequired: WithPageAuthRequired = (...args: any[]): any =>
withPageAuthRequiredFactory(getLoginUrl(), getSession)(...args);
export const withPageAuthRequired: WithPageAuthRequired = withPageAuthRequiredFactory(getLoginUrl(), getSession);
export const handleLogin: HandleLogin = (...args) => getInstance().handleLogin(...args);
export const handleLogout: HandleLogout = (...args) => getInstance().handleLogout(...args);
export const handleCallback: HandleCallback = (...args) => getInstance().handleCallback(...args);
export const handleProfile: HandleProfile = (...args) => getInstance().handleProfile(...args);
export const handleAuth: HandleAuth = (...args) => getInstance().handleAuth(...args);

export { UserProvider, UserProviderProps, UserProfile, UserContext, useUser } from './frontend';
export {
UserProvider,
UserProviderProps,
UserProfile,
UserContext,
useUser,
WithPageAuthRequiredProps
} from './frontend';

export {
ConfigParameters,
Expand Down
7 changes: 3 additions & 4 deletions tests/frontend/with-page-auth-required.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ describe('with-page-auth-required csr', () => {
await waitFor(() => expect(screen.queryByText('Private')).not.toBeInTheDocument());
});

it('should allow access to a CSR page when authenticated', async () => {
const MyPage = (): JSX.Element => <>Private</>;
const ProtectedPage = withPageAuthRequired(MyPage);
it('should add user to props of CSR page when authenticated', async () => {
const ProtectedPage = withPageAuthRequired(({ user }): JSX.Element => <>{user.email}</>);

render(<ProtectedPage />, { wrapper: withUserProvider({ user }) });
await waitFor(() => expect(window.location.assign).not.toHaveBeenCalled());
await waitFor(() => expect(screen.getByText('Private')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('foo@example.com')).toBeInTheDocument());
});

it('should show an empty element when redirecting', async () => {
Expand Down

0 comments on commit bba8851

Please sign in to comment.