فهرست منبع

feat(client): implement server-side redirect to authenticated pages

Nicolas Meienberger 2 سال پیش
والد
کامیت
c709128bba

+ 27 - 0
src/@types/next.d.ts

@@ -0,0 +1,27 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { IncomingMessage } from 'http';
+import { Session } from 'express-session';
+import { GetServerSidePropsContext, GetServerSidePropsResult, PreviewData } from 'next';
+import { ParsedUrlQuery } from 'querystring';
+
+type SessionContent = {
+  userId?: number;
+};
+
+interface ExtendedGetServerSidePropsContext<Params, Preview> extends GetServerSidePropsContext<Params, Preview> {
+  req: IncomingMessage & { session: Session & SessionContent };
+}
+
+declare module 'express-session' {
+  export type SessionData = SessionContent;
+}
+
+declare module 'next' {
+  export interface NextApiRequest extends IncomingMessage {
+    session: Session & SessionContent;
+  }
+
+  export type GetServerSideProps<Props extends { [key: string]: any } = { [key: string]: any }, Params extends ParsedUrlQuery = ParsedUrlQuery, Preview extends PreviewData = PreviewData> = (
+    ctx: ExtendedGetServerSidePropsContext<Params, Preview>,
+  ) => Promise<GetServerSidePropsResult<Props>>;
+}

+ 16 - 0
src/client/utils/page-helpers.ts

@@ -0,0 +1,16 @@
+import { GetServerSideProps } from 'next';
+
+export const getAuthedPageProps: GetServerSideProps = async (ctx) => {
+  const { userId } = ctx.req.session;
+
+  if (!userId) {
+    return {
+      redirect: {
+        destination: '/login',
+        permanent: false,
+      },
+    };
+  }
+
+  return { props: {} };
+};

+ 5 - 10
src/client/utils/trpc.ts

@@ -17,8 +17,6 @@ function getBaseUrl() {
   return `http://localhost:${process.env.PORT ?? 3000}`;
   return `http://localhost:${process.env.PORT ?? 3000}`;
 }
 }
 
 
-let token: string | null = '';
-
 export const trpc = createTRPCNext<AppRouter>({
 export const trpc = createTRPCNext<AppRouter>({
   config() {
   config() {
     return {
     return {
@@ -29,14 +27,11 @@ export const trpc = createTRPCNext<AppRouter>({
         }),
         }),
         httpBatchLink({
         httpBatchLink({
           url: `${getBaseUrl()}/api/trpc`,
           url: `${getBaseUrl()}/api/trpc`,
-          headers() {
-            if (typeof window !== 'undefined') {
-              token = localStorage.getItem('token');
-            }
-
-            return {
-              authorization: token ? `Bearer ${token}` : '',
-            };
+          fetch(url, options) {
+            return fetch(url, {
+              ...options,
+              credentials: 'include',
+            });
           },
           },
         }),
         }),
       ],
       ],

+ 16 - 0
src/pages/app-store/[id].tsx

@@ -1 +1,17 @@
+import { Context } from '@/server/context';
+import { getAuthedPageProps } from '@/utils/page-helpers';
+import { GetServerSidePropsContext } from 'next';
+
 export { AppDetailsPage as default } from '../../client/modules/Apps/pages/AppDetailsPage';
 export { AppDetailsPage as default } from '../../client/modules/Apps/pages/AppDetailsPage';
+
+export const getServerSideProps = async (ctx: Context & GetServerSidePropsContext) => {
+  const authedProps = await getAuthedPageProps(ctx);
+
+  const { id } = ctx.query;
+  const appId = String(id);
+
+  return {
+    ...authedProps,
+    props: { appId },
+  };
+};

+ 12 - 0
src/pages/app-store/index.tsx

@@ -1 +1,13 @@
+import { getAuthedPageProps } from '@/utils/page-helpers';
+import { GetServerSideProps } from 'next';
+
 export { AppStorePage as default } from '../../client/modules/AppStore/pages/AppStorePage';
 export { AppStorePage as default } from '../../client/modules/AppStore/pages/AppStorePage';
+
+export const getServerSideProps: GetServerSideProps = async (ctx) => {
+  const authedProps = await getAuthedPageProps(ctx);
+
+  return {
+    ...authedProps,
+    props: {},
+  };
+};

+ 16 - 0
src/pages/apps/[id].tsx

@@ -1 +1,17 @@
+import { Context } from '@/server/context';
+import { getAuthedPageProps } from '@/utils/page-helpers';
+import { GetServerSidePropsContext } from 'next';
+
 export { AppDetailsPage as default } from '../../client/modules/Apps/pages/AppDetailsPage';
 export { AppDetailsPage as default } from '../../client/modules/Apps/pages/AppDetailsPage';
+
+export const getServerSideProps = async (ctx: Context & GetServerSidePropsContext) => {
+  const authedProps = await getAuthedPageProps(ctx);
+
+  const { id } = ctx.query;
+  const appId = String(id);
+
+  return {
+    ...authedProps,
+    props: { appId },
+  };
+};

+ 12 - 0
src/pages/apps/index.tsx

@@ -1 +1,13 @@
+import { getAuthedPageProps } from '@/utils/page-helpers';
+import { GetServerSideProps } from 'next';
+
 export { AppsPage as default } from '../../client/modules/Apps/pages/AppsPage';
 export { AppsPage as default } from '../../client/modules/Apps/pages/AppsPage';
+
+export const getServerSideProps: GetServerSideProps = async (ctx) => {
+  const authedProps = await getAuthedPageProps(ctx);
+
+  return {
+    ...authedProps,
+    props: {},
+  };
+};

+ 12 - 0
src/pages/index.tsx

@@ -1 +1,13 @@
+import { getAuthedPageProps } from '@/utils/page-helpers';
+import { GetServerSideProps } from 'next';
+
 export { DashboardPage as default } from '../client/modules/Dashboard/pages/DashboardPage';
 export { DashboardPage as default } from '../client/modules/Dashboard/pages/DashboardPage';
+
+export const getServerSideProps: GetServerSideProps = async (ctx) => {
+  const authedProps = await getAuthedPageProps(ctx);
+
+  return {
+    ...authedProps,
+    props: {},
+  };
+};

+ 8 - 0
src/pages/login.tsx

@@ -1 +1,9 @@
+import { GetServerSideProps } from 'next';
+
 export { LoginPage as default } from '../client/modules/Auth/pages/LoginPage';
 export { LoginPage as default } from '../client/modules/Auth/pages/LoginPage';
+
+export const getServerSideProps: GetServerSideProps = async () => {
+  return {
+    props: {},
+  };
+};

+ 8 - 0
src/pages/register.tsx

@@ -1 +1,9 @@
+import { GetServerSideProps } from 'next';
+
 export { RegisterPage as default } from '../client/modules/Auth/pages/RegisterPage';
 export { RegisterPage as default } from '../client/modules/Auth/pages/RegisterPage';
+
+export const getServerSideProps: GetServerSideProps = async () => {
+  return {
+    props: {},
+  };
+};

+ 12 - 0
src/pages/settings.tsx

@@ -1 +1,13 @@
+import { getAuthedPageProps } from '@/utils/page-helpers';
+import { GetServerSideProps } from 'next';
+
 export { SettingsPage as default } from '../client/modules/Settings/pages/SettingsPage';
 export { SettingsPage as default } from '../client/modules/Settings/pages/SettingsPage';
+
+export const getServerSideProps: GetServerSideProps = async (ctx) => {
+  const authedProps = await getAuthedPageProps(ctx);
+
+  return {
+    ...authedProps,
+    props: {},
+  };
+};