Просмотр исходного кода

Merge pull request #10548 from growilabs/fix/174433-accessing-share-link-redirects-to-login-page

fix: Accessing share link redirects to login page
Yuki Takei 4 месяцев назад
Родитель
Сommit
65f53e8564

+ 3 - 14
apps/app/src/pages/share/[[...path]]/index.page.tsx

@@ -1,5 +1,4 @@
 import type { JSX, ReactNode } from 'react';
-import React from 'react';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import Head from 'next/head';
@@ -50,11 +49,12 @@ const isInitialProps = (props: Props): props is InitialProps => {
 
 const SharedPage: NextPageWithLayout<Props> = (props: Props) => {
   // Initialize Jotai atoms with initial data - must be called unconditionally
-  const pageData = isInitialProps(props) ? props.page : undefined;
+  const pageData = isInitialProps(props) ? props.pageWithMeta?.data : undefined;
+  const pageMeta = isInitialProps(props) ? props.pageWithMeta?.meta : undefined;
   const shareLink = isInitialProps(props) ? props.shareLink : undefined;
   const isExpired = isInitialProps(props) ? props.isExpired : undefined;
 
-  useHydratePageAtoms(pageData, undefined, {
+  useHydratePageAtoms(pageData, pageMeta, {
     shareLinkId: shareLink?._id,
   });
 
@@ -157,17 +157,6 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
   ) {
     return commonEachPropsResult;
   }
-  const commonEachProps = await commonEachPropsResult.props;
-
-  // Handle redirect destination from common props
-  if (commonEachProps.redirectDestination != null) {
-    return {
-      redirect: {
-        permanent: false,
-        destination: commonEachProps.redirectDestination,
-      },
-    };
-  }
 
   //
   // STAGE 2

+ 47 - 32
apps/app/src/pages/share/[[...path]]/page-data-props.ts

@@ -1,6 +1,6 @@
 import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
 import type { IPage } from '@growi/core';
-import { getIdForRef } from '@growi/core';
+import { getIdStringForRef } from '@growi/core';
 import type { model } from 'mongoose';
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
@@ -14,11 +14,27 @@ let mongooseModel: typeof model;
 let Page: PageModel;
 let ShareLink: ShareLinkModel;
 
+const notFoundProps: GetServerSidePropsResult<ShareLinkPageStatesProps> = {
+  props: {
+    isNotFound: true,
+    pageWithMeta: {
+      data: null,
+      meta: {
+        isNotFound: true,
+        isForbidden: false,
+      },
+    },
+    isExpired: undefined,
+    shareLink: undefined,
+  },
+};
+
 export const getPageDataForInitial = async (
   context: GetServerSidePropsContext,
 ): Promise<GetServerSidePropsResult<ShareLinkPageStatesProps>> => {
   const req = context.req as CrowiRequest;
   const { crowi, params } = req;
+  const { pageService, configManager } = crowi;
 
   if (mongooseModel == null) {
     mongooseModel = (await import('mongoose')).model;
@@ -36,63 +52,62 @@ export const getPageDataForInitial = async (
 
   // not found
   if (shareLink == null) {
-    return {
-      props: {
-        isNotFound: true,
-        page: null,
-        isExpired: undefined,
-        shareLink: undefined,
-      },
-    };
+    return notFoundProps;
+  }
+
+  const pageId = getIdStringForRef(shareLink.relatedPage);
+  const pageWithMeta = await pageService.findPageAndMetaDataByViewer(
+    pageId,
+    null,
+    undefined, // no user for share link
+    true, // isSharedPage
+  );
+
+  // not found
+  if (pageWithMeta.data == null) {
+    return notFoundProps;
   }
 
   // expired
   if (shareLink.isExpired()) {
+    const populatedPage =
+      await pageWithMeta.data.populateDataToShowRevision(true); //shouldExcludeBody = false,
     return {
       props: {
         isNotFound: false,
-        page: null,
+        pageWithMeta: {
+          data: populatedPage,
+          meta: pageWithMeta.meta,
+        },
         isExpired: true,
-        shareLink,
-      },
-    };
-  }
-
-  // retrieve Page
-  const relatedPage = await Page.findOne({
-    _id: getIdForRef(shareLink.relatedPage),
-  });
-
-  // not found
-  if (relatedPage == null) {
-    return {
-      props: {
-        isNotFound: true,
-        page: null,
-        isExpired: undefined,
-        shareLink: undefined,
+        shareLink: shareLink.toObject(),
       },
     };
   }
 
   // Handle existing page
-  const ssrMaxRevisionBodyLength = crowi.configManager.getConfig(
+  const ssrMaxRevisionBodyLength = configManager.getConfig(
     'app:ssrMaxRevisionBodyLength',
   );
 
   // Check if SSR should be skipped
   const latestRevisionBodyLength =
-    await relatedPage.getLatestRevisionBodyLength();
+    await pageWithMeta.data.getLatestRevisionBodyLength();
   const skipSSR =
     latestRevisionBodyLength != null &&
     ssrMaxRevisionBodyLength < latestRevisionBodyLength;
 
-  const populatedPage = await relatedPage.populateDataToShowRevision(skipSSR);
+  // Populate page data for display
+  const populatedPage =
+    await pageWithMeta.data.populateDataToShowRevision(skipSSR);
 
   return {
     props: {
       isNotFound: false,
-      page: populatedPage,
+      pageWithMeta: {
+        data: populatedPage,
+        meta: pageWithMeta.meta,
+      },
       skipSSR,
       isExpired: false,
       shareLink: shareLink.toObject(),

+ 14 - 5
apps/app/src/pages/share/[[...path]]/types.ts

@@ -1,8 +1,14 @@
-import type { IPagePopulatedToShowRevision } from '@growi/core/dist/interfaces';
+import type {
+  IDataWithRequiredMeta,
+  IPageNotFoundInfo,
+} from '@growi/core/dist/interfaces';
 
 import type { IShareLinkHasId } from '~/interfaces/share-link';
 import type { CommonEachProps, CommonInitialProps } from '~/pages/common-props';
-import type { GeneralPageInitialProps } from '~/pages/general-page';
+import type {
+  GeneralPageInitialProps,
+  IPageToShowRevisionWithMeta,
+} from '~/pages/general-page';
 
 export type ShareLinkPageStatesProps = Pick<
   GeneralPageInitialProps,
@@ -10,19 +16,22 @@ export type ShareLinkPageStatesProps = Pick<
 > &
   (
     | {
-        page: null;
+        // not found case
+        pageWithMeta: IDataWithRequiredMeta<null, IPageNotFoundInfo>;
         isNotFound: true;
         isExpired: undefined;
         shareLink: undefined;
       }
     | {
-        page: null;
+        // expired case
+        pageWithMeta: IPageToShowRevisionWithMeta;
         isNotFound: false;
         isExpired: true;
         shareLink: IShareLinkHasId;
       }
     | {
-        page: IPagePopulatedToShowRevision;
+        // normal case
+        pageWithMeta: IPageToShowRevisionWithMeta;
         isNotFound: false;
         isExpired: false;
         shareLink: IShareLinkHasId;