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

fix: persist user activity on page view and enhance activity action handling

Shun Miyazawa 3 месяцев назад
Родитель
Сommit
514f8f7440

+ 18 - 10
apps/app/src/pages/[[...path]]/page-data-props.ts

@@ -2,10 +2,11 @@ import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
 import type {
   IDataWithRequiredMeta,
   IPage,
+  IPageInfoExt,
   IPageNotFoundInfo,
   IUser,
-} from '@growi/core/dist/interfaces';
-import { isIPageInfo, isIPageNotFoundInfo } from '@growi/core/dist/interfaces';
+} from '@growi/core';
+import { isIPageInfo, isIPageNotFoundInfo } from '@growi/core';
 import {
   isPermalink as _isPermalink,
   isTopPage,
@@ -15,7 +16,7 @@ import assert from 'assert';
 import type { HydratedDocument, model } from 'mongoose';
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
-import type { PageModel } from '~/server/models/page';
+import type { PageDocument, PageModel } from '~/server/models/page';
 import type {
   IPageRedirect,
   PageRedirectModel,
@@ -252,11 +253,14 @@ export async function getPageDataForSameRoute(
   props: Pick<CommonEachProps, 'currentPathname'> &
     Pick<EachProps, 'currentPathname' | 'isIdenticalPathPage' | 'redirectFrom'>;
   internalProps?: {
-    pageId?: string;
+    pageWithMeta?:
+      | IDataWithRequiredMeta<PageDocument, IPageInfoExt>
+      | IDataWithRequiredMeta<null, IPageNotFoundInfo>;
   };
 }> {
   const req: CrowiRequest = context.req as CrowiRequest;
-  const { user } = req;
+  const { crowi, user } = req;
+  const { pageService, pageGrantService } = crowi;
 
   const pathname = decodeURIComponent(
     context.resolvedUrl?.split('?')[0] ?? '/',
@@ -278,13 +282,17 @@ export async function getPageDataForSameRoute(
   }
 
   // For same route access, do minimal page lookup
-  const basicPageInfo = await Page.findOne(
-    isPermalink ? { _id: pageId } : { path: resolvedPagePath },
-  ).exec();
+  const pageWithMeta = await findPageAndMetaDataByViewer(
+    pageService,
+    pageGrantService,
+    pageId,
+    resolvedPagePath,
+    user,
+  );
 
   const currentPathname = resolveFinalizedPathname(
     resolvedPagePath,
-    basicPageInfo,
+    pageWithMeta.data,
     isPermalink,
   );
 
@@ -295,7 +303,7 @@ export async function getPageDataForSameRoute(
       redirectFrom,
     },
     internalProps: {
-      pageId: basicPageInfo?._id?.toString(),
+      pageWithMeta,
     },
   };
 }

+ 55 - 7
apps/app/src/pages/[[...path]]/server-side-props.ts

@@ -1,6 +1,19 @@
 import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
+import type {
+  IDataWithMeta,
+  IDataWithRequiredMeta,
+  IPageInfoExt,
+  IPageNotFoundInfo,
+} from '@growi/core';
+import { isIPageNotFoundInfo } from '@growi/core';
+import { pagePathUtils } from '@growi/core/dist/utils';
 
+import {
+  SupportedAction,
+  type SupportedActionType,
+} from '~/interfaces/activity';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
+import type { PageDocument } from '~/server/models/page';
 
 import { getServerSideBasicLayoutProps } from '../basic-layout-page';
 import {
@@ -8,11 +21,11 @@ import {
   getServerSideI18nProps,
 } from '../common-props';
 import {
-  getActivityAction,
   getServerSideGeneralPageProps,
   getServerSideRendererConfigProps,
 } from '../general-page';
 import { isValidGeneralPageInitialProps } from '../general-page/type-guards';
+import type { IPageToShowRevisionWithMeta } from '../general-page/types';
 import { addActivity } from '../utils/activity';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { NEXT_JS_ROUTING_PAGE } from './consts';
@@ -52,6 +65,37 @@ function emitPageSeenEvent(
   pageEvent.emit('seen', pageId, user);
 }
 
+function getActivityAction(
+  pageWithMeta?:
+    | IPageToShowRevisionWithMeta
+    | IDataWithRequiredMeta<PageDocument, IPageInfoExt>
+    | IDataWithMeta<null, IPageNotFoundInfo>
+    | null,
+): SupportedActionType {
+  const pagePath = pageWithMeta?.data?.path;
+
+  const meta = pageWithMeta?.meta;
+  if (isIPageNotFoundInfo(meta)) {
+    if (meta.isForbidden) {
+      return SupportedAction.ACTION_PAGE_FORBIDDEN;
+    }
+
+    if (meta.isNotFound) {
+      return SupportedAction.ACTION_PAGE_NOT_FOUND;
+    }
+  }
+
+  if (pagePath != null && pagePathUtils.isUsersHomepage(pagePath)) {
+    return SupportedAction.ACTION_PAGE_USER_HOME_VIEW;
+  }
+
+  if (pagePath != null && !pagePathUtils.isCreatablePage(pagePath)) {
+    return SupportedAction.ACTION_PAGE_NOT_CREATABLE;
+  }
+
+  return SupportedAction.ACTION_PAGE_VIEW;
+}
+
 export async function getServerSidePropsForInitial(
   context: GetServerSidePropsContext,
 ): Promise<GetServerSidePropsResult<Stage2InitialProps>> {
@@ -104,8 +148,9 @@ export async function getServerSidePropsForInitial(
   // Add user to seen users
   emitPageSeenEvent(context, mergedProps.pageWithMeta?.data?._id);
 
-  // -- TODO: persist activity
-  // await addActivity(context, getActivityAction(mergedProps));
+  // Persist activity
+  addActivity(context, getActivityAction(mergedProps.pageWithMeta));
+
   return mergedResult;
 }
 
@@ -122,11 +167,14 @@ export async function getServerSidePropsForSameRoute(
   const { props: pageDataProps, internalProps } = pageDataForSameRouteResult;
 
   // Add user to seen users
-  emitPageSeenEvent(context, internalProps?.pageId);
+  emitPageSeenEvent(
+    context,
+    internalProps?.pageWithMeta?.data?._id?.toString(),
+  );
+
+  // Persist activity
+  addActivity(context, getActivityAction(internalProps?.pageWithMeta));
 
-  // -- TODO: persist activity
-  // const mergedProps = await mergedResult.props;
-  // await addActivity(context, getActivityAction(mergedProps));
   const mergedResult = mergeGetServerSidePropsResults(
     { props: pageDataProps },
     i18nPropsResult,