javascript - Skapa T3-app Omdirigera inom ett TRPC-mellanskikt om användaren inte är inloggad


Hur kan jag utlösa en omdirigering på serversidan om en inloggad användare inte har slutfört sin profilsida

const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.session || !ctx.session.user) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }

  // redirect to profile page if user has not completed profile


  return next({
    ctx: {
      // infers the `session` as non-nullable
      session: { ...ctx.session, user: ctx.session.user },
    },
  });
});

Svar #1

Detta är för närvarande inte möjligt på det sätt som du beskriver enligt vad jag vet.

Här är några alternativ som kan vara användbara:

I getServerSideProps

detta fungerar endast om du vill omdirigera innan den initiala sidladdningen. Du kan också skapa ett omslag runt gSSP för att göra detta mer DRY om du kommer att använda det på många sidor.

import { type GetServerSidePropsContext } from "next";
import { getServerAuthSession } from "../server/auth";

export async function getServerSideProps(ctx: GetServerSidePropsContext) {
  const session = await getServerAuthSession(ctx);

  if (!session) {
    return {
      redirect: {
        destination: "/",
        permanent: false,
      },
    };
  }

  return {
    props: {},
  };
}

export default function AuthedPage() {
  return <div>Authed</div>;
}

Som en del av en fråga eller mutation på klientsidan

detta är användbart för en fråga eller mutation som endast körs efter att sidan har laddats. Återigen är detta ett mycket enkelt exempel och skulle kunna göras mer DRY, förmodligen det enklaste sättet skulle vara att extrahera det till en egen hook.

import { useRouter } from "next/router";
import { api } from "../utils/api";

export default function AuthedPage() {
  const router = useRouter();

  // `authedHello` is the example Create T3 App "hello" procedure
  // but as a protectedProcedure, ie throws "UNAUTHORIZED" if no session.
  // Replace this with a middleware that throws on whatever condition you need it to.
  const authedHello = api.example.protectedHello.useQuery(
    { text: "world" },
    {
      retry: (_count, err) => {
        // `onError` only runs once React Query stops retrying
        if (err.data?.code === "UNAUTHORIZED") {
          return false;
        }
        return true;
      },
      onError: (err) => {
        if (err.data?.code === "UNAUTHORIZED") {
          void router.push("/");
        }
      },
    }
  );

  return (
    <div>
      <h1>Authed Page</h1>
      <p>{authedHello.data?.greeting}</p>
    </div>
  );
}

Använda Next.js-mellanprogram

Detta är lätt att tillämpa på en massa rutter med hjälp av matcharen, men det ligger lite utanför T3-konventionerna.

// pages/middleware.ts
import { NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "../server/auth";
import type { NextApiRequest, NextApiResponse } from "next";

export async function middleware(req: NextApiRequest, res: NextApiResponse) {
  const session = await getServerSession(req, res, authOptions);
  if (!session?.user) {
    return NextResponse.redirect(new URL("/", req.url));
  }
}

export const config = {
  matcher: ["/protectedPage", "/anotherProtectedPage"],
};

Att använda require i next-auths useSession

detta är användbart om du vill skydda en sida men inte kan använda getServerSideProps. Det löser inte riktigt ditt specifika problem, men kan vara användbart för andra som hittar detta. Se: https://next-auth.js.org/getting-started/client#require-session

Relaterade artiklar