Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(examples/auth): migrates to 3.0 #5877

Merged
merged 39 commits into from
May 3, 2024
Merged

chore(examples/auth): migrates to 3.0 #5877

merged 39 commits into from
May 3, 2024

Conversation

jacobsfletch
Copy link
Member

@jacobsfletch jacobsfletch commented Apr 16, 2024

Description

Updates the Auth Example to use Payload 3.0 (integrated Payload + Next.js App Router). This PR:

  • Installs 3.0 beta into the payload dir and builds an integrated Next.js app using the Local API for auth

    • Migrates from a server-side fetch to calling the payload.auth operation
      import { headers } from 'next/headers'
      import { redirect } from 'next/navigation'
      import { getPayloadHMR } from '@payloadcms/next/utilities'
      
      import config from './payload.config'
      
      export default async function Account() {
        const payload = await getPayloadHMR({ config })
        const { user } = await payload.auth({ headers: getHeaders() })
      
         if (!user) redirect('/login')
      
        return <h1>{`Hello, ${user.email}!`}</h1>
      }
  • Establishes a pattern for the remaining examples, i.e.:

    • How to continue to showcase other frameworks alongside Payload 3.0 (which ships with its own Next.js front-end)
    • Moves initial database seed function to an official migration script
    • Migration from yarn to pnpm (not required, but our examples will now default to pnpm)
    • Updated READMEs
    • Other misc. housekeeping like ESLint config, module resolution, etc.
  • I have read and understand the CONTRIBUTING.md document in this repository.

@r1tsuu
Copy link
Contributor

r1tsuu commented Apr 16, 2024

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)

@jacobsfletch
Copy link
Member Author

jacobsfletch commented Apr 16, 2024

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.

@jacobsfletch jacobsfletch changed the title chore(examples/auth): adds 3.0 example chore(examples/auth): updates auth example to 3.0 Apr 23, 2024
@jacobsfletch jacobsfletch changed the title chore(examples/auth): updates auth example to 3.0 chore(examples): updates auth example to 3.0 May 3, 2024
@jacobsfletch jacobsfletch marked this pull request as ready for review May 3, 2024 14:39
@jacobsfletch jacobsfletch requested a review from denolfe as a code owner May 3, 2024 14:39
@jacobsfletch
Copy link
Member Author

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.

@r1tsuu
Copy link
Contributor

r1tsuu commented May 3, 2024

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.

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);

@jacobsfletch
Copy link
Member Author

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.

@r1tsuu
Copy link
Contributor

r1tsuu commented May 3, 2024

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.

@jacobsfletch
Copy link
Member Author

jacobsfletch commented May 3, 2024

@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.

@jacobsfletch jacobsfletch changed the title chore(examples): updates auth example to 3.0 chore(examples/auth): migrates to 3.0 May 3, 2024
@jacobsfletch jacobsfletch merged commit 07f2d74 into beta May 3, 2024
9 checks passed
@jacobsfletch jacobsfletch deleted the examples/auth branch May 3, 2024 20:28
paulpopus pushed a commit that referenced this pull request May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants