feat: returns queried user alongside refreshed token (#2813)
Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
This commit is contained in:
29
test/auth/AuthDebug.tsx
Normal file
29
test/auth/AuthDebug.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useAuth } from '../../src/admin/components/utilities/Auth';
|
||||
import { User } from '../../src/auth';
|
||||
import { UIField } from '../../src/fields/config/types';
|
||||
|
||||
export const AuthDebug: React.FC<UIField> = () => {
|
||||
const [state, setState] = useState<User | null | undefined>();
|
||||
const { user } = useAuth();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUser = async () => {
|
||||
const userRes = await fetch(`/api/users/${user?.id}`)?.then((res) => res.json());
|
||||
setState(userRes);
|
||||
};
|
||||
|
||||
fetchUser();
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
<div id="auth-debug">
|
||||
<div id="use-auth-result">
|
||||
{user?.custom as string}
|
||||
</div>
|
||||
<div id="users-api-result">
|
||||
{state?.custom as string}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -2,6 +2,7 @@ import { v4 as uuid } from 'uuid';
|
||||
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||
import { buildConfig } from '../buildConfig';
|
||||
import { devUser } from '../credentials';
|
||||
import { AuthDebug } from './AuthDebug';
|
||||
|
||||
export const slug = 'users';
|
||||
|
||||
@@ -36,6 +37,21 @@ export default buildConfig({
|
||||
saveToJWT: true,
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'custom',
|
||||
label: 'Custom',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'authDebug',
|
||||
label: 'Auth Debug',
|
||||
type: 'ui',
|
||||
admin: {
|
||||
components: {
|
||||
Field: AuthDebug,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -65,6 +81,7 @@ export default buildConfig({
|
||||
data: {
|
||||
email: devUser.email,
|
||||
password: devUser.password,
|
||||
custom: 'Hello, world!',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||
import { initPayloadE2E } from '../helpers/configHelpers';
|
||||
import { login, saveDocAndAssert } from '../helpers';
|
||||
@@ -42,5 +42,19 @@ describe('auth', () => {
|
||||
|
||||
await saveDocAndAssert(page);
|
||||
});
|
||||
|
||||
test('should have up-to-date user in `useAuth` hook', async () => {
|
||||
await page.goto(url.account);
|
||||
|
||||
await expect(await page.locator('#users-api-result')).toHaveText('Hello, world!');
|
||||
await expect(await page.locator('#use-auth-result')).toHaveText('Hello, world!');
|
||||
|
||||
const field = await page.locator('#field-custom');
|
||||
await field.fill('Goodbye, world!');
|
||||
await saveDocAndAssert(page);
|
||||
|
||||
await expect(await page.locator('#users-api-result')).toHaveText('Goodbye, world!');
|
||||
await expect(await page.locator('#use-auth-result')).toHaveText('Goodbye, world!');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import payload from '../../src';
|
||||
import { initPayloadTest } from '../helpers/configHelpers';
|
||||
import { slug } from './config';
|
||||
import { devUser } from '../credentials';
|
||||
import type { User } from '../../src/auth';
|
||||
|
||||
require('isomorphic-fetch');
|
||||
|
||||
@@ -11,6 +12,7 @@ let apiUrl;
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const { email, password } = devUser;
|
||||
|
||||
describe('Auth', () => {
|
||||
@@ -68,6 +70,8 @@ describe('Auth', () => {
|
||||
|
||||
describe('logged in', () => {
|
||||
let token: string | undefined;
|
||||
let loggedInUser: User | undefined;
|
||||
|
||||
beforeAll(async () => {
|
||||
const response = await fetch(`${apiUrl}/${slug}/login`, {
|
||||
body: JSON.stringify({
|
||||
@@ -80,6 +84,7 @@ describe('Auth', () => {
|
||||
|
||||
const data = await response.json();
|
||||
token = data.token;
|
||||
loggedInUser = data.user;
|
||||
});
|
||||
|
||||
it('should return a logged in user from /me', async () => {
|
||||
@@ -99,6 +104,7 @@ describe('Auth', () => {
|
||||
|
||||
it('should allow authentication with an API key with useAPIKey', async () => {
|
||||
const apiKey = '0123456789ABCDEFGH';
|
||||
|
||||
const user = await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
@@ -107,10 +113,11 @@ describe('Auth', () => {
|
||||
apiKey,
|
||||
},
|
||||
});
|
||||
|
||||
const response = await fetch(`${apiUrl}/${slug}/me`, {
|
||||
headers: {
|
||||
...headers,
|
||||
Authorization: `${slug} API-Key ${user.apiKey}`,
|
||||
Authorization: `${slug} API-Key ${user?.apiKey}`,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -135,6 +142,30 @@ describe('Auth', () => {
|
||||
expect(data.refreshedToken).toBeDefined();
|
||||
});
|
||||
|
||||
it('should refresh a token and receive an up-to-date user', async () => {
|
||||
expect(loggedInUser?.custom).toBe('Hello, world!');
|
||||
|
||||
await payload.update({
|
||||
collection: slug,
|
||||
id: loggedInUser?.id || '',
|
||||
data: {
|
||||
custom: 'Goodbye, world!',
|
||||
},
|
||||
});
|
||||
|
||||
const response = await fetch(`${apiUrl}/${slug}/refresh-token`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
Authorization: `JWT ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(data.user.custom).toBe('Goodbye, world!');
|
||||
});
|
||||
|
||||
it('should allow a user to be created', async () => {
|
||||
const response = await fetch(`${apiUrl}/${slug}`, {
|
||||
body: JSON.stringify({
|
||||
@@ -201,6 +232,7 @@ describe('Auth', () => {
|
||||
expect(verificationResponse.status).toBe(200);
|
||||
|
||||
const afterVerifyResult = await db.collection('public-users').findOne({ email: emailToVerify });
|
||||
// @ts-expect-error trust
|
||||
const { _verified: afterVerified, _verificationToken: afterToken } = afterVerifyResult;
|
||||
expect(afterVerified).toBe(true);
|
||||
expect(afterToken).toBeUndefined();
|
||||
|
||||
28
test/auth/ui/AuthDebug.tsx
Normal file
28
test/auth/ui/AuthDebug.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useAuth } from '../../../src/admin/components/utilities/Auth';
|
||||
import { UIField } from '../../../src/fields/config/types';
|
||||
import { User } from '../../../src/auth';
|
||||
|
||||
export const AuthDebug: React.FC<UIField> = () => {
|
||||
const [state, setState] = useState<User | null | undefined>();
|
||||
const { user } = useAuth();
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
fetch(`/api/users/${user.id}`).then((r) => r.json()).then((newUser) => {
|
||||
setState(newUser);
|
||||
});
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
<div id="auth-debug-ui-field">
|
||||
<div id="users-api-result">
|
||||
{state?.custom as string}
|
||||
</div>
|
||||
<div id="use-auth-result">
|
||||
{user?.custom as string}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user