Skip to content

Commit

Permalink
feat(adapter-nextjs): add user has signed in check before initiating …
Browse files Browse the repository at this point in the history
…sign-in and sign-up
  • Loading branch information
HuiSF committed Oct 1, 2024
1 parent 284acbf commit df708b8
Show file tree
Hide file tree
Showing 12 changed files with 394 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ const mockIsNextRequest = jest.mocked(isNextRequest);
const mockIsAuthRoutesHandlersContext = jest.mocked(
isAuthRoutesHandlersContext,
);
const mockRunWithAmplifyServerContext =
jest.fn() as jest.MockedFunction<NextServer.RunOperationWithContext>;

describe('createAuthRoutesHandlersFactory', () => {
const existingProcessEnvVars = { ...process.env };
Expand All @@ -84,6 +86,7 @@ describe('createAuthRoutesHandlersFactory', () => {
createAuthRouteHandlersFactory({
config: mockAmplifyConfig,
runtimeOptions: mockRuntimeOptions,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
}),
).toThrow('Could not find the AMPLIFY_APP_ORIGIN environment variable.');
});
Expand All @@ -92,6 +95,7 @@ describe('createAuthRoutesHandlersFactory', () => {
createAuthRouteHandlersFactory({
config: mockAmplifyConfig,
runtimeOptions: mockRuntimeOptions,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockAssertTokenProviderConfig).toHaveBeenCalledWith(
Expand All @@ -106,6 +110,7 @@ describe('createAuthRoutesHandlersFactory', () => {
const testCreateAuthRoutesHandlersFactoryInput = {
config: mockAmplifyConfig,
runtimeOptions: mockRuntimeOptions,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
};
const testCreateAuthRoutesHandlersInput: CreateAuthRoutesHandlersInput = {
customState: 'random-state',
Expand Down Expand Up @@ -151,6 +156,7 @@ describe('createAuthRoutesHandlersFactory', () => {
setCookieOptions: mockRuntimeOptions.cookies,
origin: 'https://example.com',
userPoolClientId: 'def',
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});
});

Expand All @@ -172,6 +178,7 @@ describe('createAuthRoutesHandlersFactory', () => {
setCookieOptions: mockRuntimeOptions.cookies,
origin: 'https://example.com',
userPoolClientId: 'def',
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});
});

Expand All @@ -192,6 +199,7 @@ describe('createAuthRoutesHandlersFactory', () => {
const createAuthRoutesHandlers = createAuthRouteHandlersFactory({
config: mockAmplifyConfig,
runtimeOptions: undefined,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});
const handlerWithDefaultParamValues =
createAuthRoutesHandlers(/* undefined */);
Expand All @@ -214,6 +222,7 @@ describe('createAuthRoutesHandlersFactory', () => {
setCookieOptions: {},
origin: 'https://example.com',
userPoolClientId: 'def',
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ import {
handleSignOutCallbackRequest,
handleSignOutRequest,
} from '../../src/auth/handlers';
import { NextServer } from '../../src';
import {
hasUserSignedInWithAppRouter,
isSupportedAuthApiRoutePath,
} from '../../src/auth/utils';

jest.mock('../../src/auth/handlers');
jest.mock('../../src/auth/utils');

const mockHandleSignInSignUpRequest = jest.mocked(handleSignInSignUpRequest);
const mockHandleSignOutRequest = jest.mocked(handleSignOutRequest);
Expand All @@ -23,6 +29,14 @@ const mockHandleSignInCallbackRequest = jest.mocked(
const mockHandleSignOutCallbackRequest = jest.mocked(
handleSignOutCallbackRequest,
);
const mockHasUserSignedInWithAppRouter = jest.mocked(
hasUserSignedInWithAppRouter,
);
const mockIsSupportedAuthApiRoutePath = jest.mocked(
isSupportedAuthApiRoutePath,
);
const mockRunWithAmplifyServerContext =
jest.fn() as jest.MockedFunction<NextServer.RunOperationWithContext>;

describe('handleAuthApiRouteRequestForAppRouter', () => {
const testOrigin = 'https://example.com';
Expand All @@ -40,6 +54,11 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
};
const _ = handleAuthApiRouteRequestForAppRouter;

beforeAll(() => {
mockHasUserSignedInWithAppRouter.mockResolvedValue(false);
mockIsSupportedAuthApiRoutePath.mockReturnValue(true);
});

it('returns a 405 response when input.request has an unsupported method', async () => {
const request = new NextRequest(
new URL('https://example.com/api/auth/sign-in'),
Expand All @@ -55,6 +74,7 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response.status).toBe(405);
Expand All @@ -75,6 +95,7 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response.status).toBe(400);
Expand All @@ -87,6 +108,9 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
method: 'GET',
},
);

mockIsSupportedAuthApiRoutePath.mockReturnValueOnce(false);

const response = await handleAuthApiRouteRequestForAppRouter({
request,
handlerContext: { params: { slug: 'exchange-token' } },
Expand All @@ -95,6 +119,7 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response.status).toBe(404);
Expand Down Expand Up @@ -124,6 +149,7 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response).toBe(mockResponse);
Expand All @@ -139,6 +165,36 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
},
);

test.each([['sign-in'], ['sign-up']])(
`calls hasUserSignedInWithAppRouter with correct params when handlerContext.params.slug is %s, and when it returns true, the handler returns a 302 response`,
async slug => {
mockHasUserSignedInWithAppRouter.mockResolvedValueOnce(true);
const mockRequest = new NextRequest(
new URL('https://example.com/api/auth/sign-in'),
{
method: 'GET',
},
);

const response = await handleAuthApiRouteRequestForAppRouter({
request: mockRequest,
handlerContext: { params: { slug } },
handlerInput: {
...testHandlerInput,
redirectOnSignInComplete: undefined,
},
userPoolClientId: 'userPoolClientId',
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response.status).toBe(302);
expect(response.headers.get('Location')).toBe('/');
},
);

it('calls handleSignOutRequest with correct params when handlerContext.params.slug is sign-out', async () => {
const mockRequest = new NextRequest(
new URL('https://example.com/api/auth/sign-out'),
Expand All @@ -158,6 +214,7 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response).toBe(mockResponse);
Expand Down Expand Up @@ -188,6 +245,7 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response).toBe(mockResponse);
Expand Down Expand Up @@ -220,6 +278,7 @@ describe('handleAuthApiRouteRequestForAppRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(response).toBe(mockResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ import {
handleSignOutCallbackRequestForPagesRouter,
handleSignOutRequestForPagesRouter,
} from '../../src/auth/handlers';
import { NextServer } from '../../src';
import {
hasUserSignedInWithPagesRouter,
isSupportedAuthApiRoutePath,
} from '../../src/auth/utils';

import { createMockNextApiResponse } from './testUtils';

jest.mock('../../src/auth/handlers');
jest.mock('../../src/auth/utils');

const mockHandleSignInSignUpRequestForPagesRouter = jest.mocked(
handleSignInSignUpRequestForPagesRouter,
Expand All @@ -26,6 +32,14 @@ const mockHandleSignInCallbackRequestForPagesRouter = jest.mocked(
const mockHandleSignOutCallbackRequestForPagesRouter = jest.mocked(
handleSignOutCallbackRequestForPagesRouter,
);
const mockIsSupportedAuthApiRoutePath = jest.mocked(
isSupportedAuthApiRoutePath,
);
const mockHasUserSignedInWithPagesRouter = jest.mocked(
hasUserSignedInWithPagesRouter,
);
const mockRunWithAmplifyServerContext =
jest.fn() as jest.MockedFunction<NextServer.RunOperationWithContext>;

describe('handleAuthApiRouteRequestForPagesRouter', () => {
const testOrigin = 'https://example.com';
Expand All @@ -50,6 +64,11 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
mockResponse,
} = createMockNextApiResponse();

beforeAll(() => {
mockHasUserSignedInWithPagesRouter.mockResolvedValue(false);
mockIsSupportedAuthApiRoutePath.mockReturnValue(true);
});

afterEach(() => {
mockResponseAppendHeader.mockClear();
mockResponseEnd.mockClear();
Expand All @@ -69,6 +88,7 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: testSetCookieOptions,
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockResponseStatus).toHaveBeenCalledWith(405);
Expand All @@ -86,6 +106,7 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: testSetCookieOptions,
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockResponseStatus).toHaveBeenCalledWith(400);
Expand All @@ -98,6 +119,8 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
query: { slug: 'exchange-token' },
} as any;

mockIsSupportedAuthApiRoutePath.mockReturnValueOnce(false);

handleAuthApiRouteRequestForPagesRouter({
request: mockRequest,
response: mockResponse,
Expand All @@ -106,6 +129,7 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: testSetCookieOptions,
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockResponseStatus).toHaveBeenCalledWith(404);
Expand All @@ -132,6 +156,7 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockHandleSignInSignUpRequestForPagesRouter).toHaveBeenCalledWith({
Expand All @@ -147,6 +172,34 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
},
);

test.each([['sign-in'], ['sign-up']])(
`calls hasUserSignedInWithPagesRouter with correct params when handlerContext.params.slug is %s, and when it returns true, the handler returns a 302 response`,
async slug => {
mockHasUserSignedInWithPagesRouter.mockResolvedValueOnce(true);
const mockRequest = {
url: 'https://example.com/api/auth/sign-in',
method: 'GET',
query: { slug },
} as unknown as NextApiRequest;

await handleAuthApiRouteRequestForPagesRouter({
request: mockRequest,
response: mockResponse,
handlerInput: {
...testHandlerInput,
redirectOnSignInComplete: undefined,
},
userPoolClientId: 'userPoolClientId',
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockResponseRedirect).toHaveBeenCalledWith(302, '/');
},
);

it('calls handleSignOutRequest with correct params when handlerContext.params.slug is sign-out', async () => {
const mockRequest = {
url: 'https://example.com/api/auth/sign-in',
Expand All @@ -162,6 +215,7 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockHandleSignOutRequestForPagesRouter).toHaveBeenCalledWith({
Expand All @@ -188,6 +242,7 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockHandleSignInCallbackRequestForPagesRouter).toHaveBeenCalledWith({
Expand Down Expand Up @@ -216,6 +271,7 @@ describe('handleAuthApiRouteRequestForPagesRouter', () => {
oAuthConfig: testOAuthConfig,
setCookieOptions: {},
origin: testOrigin,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

expect(mockHandleSignOutCallbackRequestForPagesRouter).toHaveBeenCalledWith(
Expand Down
Loading

0 comments on commit df708b8

Please sign in to comment.