chore(examples/auth): updates auth example to 3.0
Description
Updates auth example to use Payload 3.0 (integrated Payload + Next.js App Router). This PR does not migrate heavily to React Server Components, however (this will come later). This mainly establishes a pattern for the remaining examples, including:
-
How to continue to showcase other frameworks alongside Payload 3.0 which ships with its own Next.js front-end
-
Migration from yarn to pnpm
-
Updated README
-
[x] I have read and understand the CONTRIBUTING.md document in this repository.
Hello! I'm sorry, just asking because I'm doing auth now with 3.0 and want to know a better way, is there a specific reason why here https://github.com/payloadcms/payload/blob/6699040b2944261eb4cc20cdf4e26b9e6cb1e22f/examples/auth/payload-next/src/app/(app)/_utilities/getMeUser.ts you are using rest api instead of payload.auth? you just need to pass headers to it from Next js.
is this because you want to execute read field access as well? (meOperation finds user with overrideAccess: false so it makes sense)
Hey @r1tsuu it's no problem, happy to provide some context here. You're right in that we can lean into the Local API now instead of REST. That will definitely happen, just one step at a time. Right now we're mainly concerned with getting a new pattern for our Examples Directory so that we can continue to demonstrate traditional headless setups as well as alternative frameworks, on top of the new 3.0 paradigm. Stay tuned into this PR for a full glimpse into exactly how we suggest you setup auth in your own apps going forward.
Hey @r1tsuu just following up here. Check out the latest code where we use the initPage function to send headers, cookies, etc. to the payload.auth operation similar to as you've described. This is the same utility used in the admin panel itself.
Hey @r1tsuu just following up here. Check out the latest code where we use the
initPagefunction to send headers, cookies, etc. to thepayload.authoperation similar to as you've described. This is the same utility used in the admin panel itself.
Yeah that's nice, I've done a simillar thing which basically the same but provides the props directly to the component
import configPromise from '@payload-config';
import { headers } from 'next/headers';
import { initPage } from 'node_modules/@payloadcms/next/dist/utilities/initPage'; // it was for older beta version
import type { InitPageResult } from 'payload/types';
import React from 'react';
type ServerComponentProps = {
params?: Record<string, string>;
searchParams?: Record<string, string | string[]>;
};
export type WithPayloadComponentProps = InitPageResult & ServerComponentProps;
export const withPayload = (Component: React.FC<InitPageResult & ServerComponentProps>) => {
const ComponentWithPayload = async ({ params, searchParams }: ServerComponentProps) => {
const initPageResult = await initPage({
config: configPromise,
route: '/home',
searchParams: searchParams ?? {},
});
return <Component {...initPageResult} params={params} searchParams={searchParams} />;
};
return ComponentWithPayload;
};
async function Page(props: WithPayloadComponentProps) {
console.log(props.req.user);
const data = await props.req.payload.find({ collection: 'admins' });
return <div>{data.totalDocs}</div>;
}
export default withPayload(Page);
I'm not a huge fan of the HOC pattern here tbh simply because you still need to thread through custom args for each page, i.e. the config and the route. This adds an extra layer of complexity imo.
I'm not a huge fan of the HOC pattern here tbh simply because you still need to thread through custom args for each page, i.e. the config and the route. This adds an extra layer of complexity imo.
that's just example you can pass route to withPayload function (i forgot about this as i just tested how it can work), but i agree that simple function call is simpler here to use.
@r1tsuu after some deliberation I've went ahead and moved away from initPage altogether in favor of using the payload.auth operation directly. Here's an example:
import { headers } from 'next/headers.js'
import { getPayloadHMR } from '@payloadcms/next'
import config from '../../payload.config'
export default async function AccountPage({ searchParams }) {
const payload = await getPayloadHMR({ config: configPromise })
const { permissions, user } = await payload.auth({ headers: headers() })
if (!user) {
redirect(
`/login?error=${encodeURIComponent('You must be logged in to access your account.')}&redirect=/account`,
)
}
return ...
}
I've outlined this in the README as well.