Selaa lähdekoodia

fix group fetch for page grant fix page

Futa Arai 2 vuotta sitten
vanhempi
sitoutus
717b20e232

+ 8 - 6
apps/app/src/components/PageAlert/FixPageGrantAlert.tsx

@@ -8,6 +8,7 @@ import {
 
 import { apiv3Put } from '~/client/util/apiv3-client';
 import { toastError, toastSuccess } from '~/client/util/toastr';
+import { ExternalUserGroupDocument } from '~/features/external-user-group/server/models/external-user-group';
 import { IPageGrantData } from '~/interfaces/page';
 import { IRecordApplicableGrant, IResIsGrantNormalizedGrantData } from '~/interfaces/page-grant';
 import { UserGroupDocument } from '~/server/models/user-group';
@@ -30,11 +31,12 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
   } = props;
 
   const [selectedGrant, setSelectedGrant] = useState<PageGrant>(PageGrant.GRANT_RESTRICTED);
-  const [selectedGroup, setSelectedGroup] = useState<UserGroupDocument | undefined>(undefined);
+  const [selectedGroup, setSelectedGroup] = useState<{type: GroupType, item: UserGroupDocument | ExternalUserGroupDocument} | undefined>(undefined);
 
   // Alert message state
   const [shouldShowModalAlert, setShowModalAlert] = useState<boolean>(false);
 
+  console.log(dataApplicableGrant);
   const applicableGroups = dataApplicableGrant[PageGrant.GRANT_USER_GROUP]?.applicableGroups;
 
   // Reset state when opened
@@ -58,7 +60,7 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
     try {
       await apiv3Put(`/page/${pageId}/grant`, {
         grant: selectedGrant,
-        grantedGroups: selectedGroup?._id != null ? [{ item: selectedGroup?._id, type: GroupType.userGroup }] : null,
+        grantedGroups: selectedGroup?.item._id != null ? [{ item: selectedGroup?.item._id, type: selectedGroup.type }] : null,
       });
 
       toastSuccess(t('Successfully updated'));
@@ -186,7 +188,7 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
                       {
                         selectedGroup == null
                           ? t('fix_page_grant.modal.select_group_default_text')
-                          : selectedGroup.name
+                          : selectedGroup.item.name
                       }
                     </span>
                   </button>
@@ -194,12 +196,12 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
                     {
                       applicableGroups != null && applicableGroups.map(g => (
                         <button
-                          key={g._id}
+                          key={g.item._id}
                           className="dropdown-item"
                           type="button"
                           onClick={() => setSelectedGroup(g)}
                         >
-                          {g.name}
+                          {g.item.name}
                         </button>
                       ))
                     }
@@ -256,7 +258,7 @@ export const FixPageGrantAlert = (): JSX.Element => {
   if (!hasParent) {
     return <></>;
   }
-  if (dataIsGrantNormalized?.isGrantNormalized == null || dataIsGrantNormalized.isGrantNormalized) {
+  if (dataIsGrantNormalized?.isGrantNormalized == null || !dataIsGrantNormalized.isGrantNormalized) {
     return <></>;
   }
 

+ 3 - 2
apps/app/src/interfaces/page-grant.ts

@@ -1,11 +1,12 @@
-import { PageGrant } from '@growi/core';
+import { PageGrant, GroupType } from '@growi/core';
 
+import { ExternalUserGroupDocument } from '~/features/external-user-group/server/models/external-user-group';
 import { UserGroupDocument } from '~/server/models/user-group';
 
 import { IPageGrantData } from './page';
 
 export type IDataApplicableGroup = {
-  applicableGroups?: UserGroupDocument[]
+  applicableGroups?: {type: GroupType, item: UserGroupDocument | ExternalUserGroupDocument }[]
 }
 
 export type IDataApplicableGrant = null | IDataApplicableGroup;

+ 38 - 13
apps/app/src/server/service/page-grant.ts

@@ -1,6 +1,6 @@
 import {
   type IGrantedGroup,
-  PageGrant, type PageGrantCanBeOnTree,
+  PageGrant, type PageGrantCanBeOnTree, GroupType,
 } from '@growi/core';
 import {
   pagePathUtils, pathUtils, pageUtils,
@@ -9,11 +9,11 @@ import { et } from 'date-fns/locale';
 import escapeStringRegexp from 'escape-string-regexp';
 import mongoose from 'mongoose';
 
-import ExternalUserGroup from '~/features/external-user-group/server/models/external-user-group';
+import ExternalUserGroup, { ExternalUserGroupDocument } from '~/features/external-user-group/server/models/external-user-group';
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
 import { IRecordApplicableGrant } from '~/interfaces/page-grant';
 import { PageDocument, PageModel } from '~/server/models/page';
-import UserGroup from '~/server/models/user-group';
+import UserGroup, { UserGroupDocument } from '~/server/models/user-group';
 import { includesObjectIds, excludeTestIdsFromTargetIds } from '~/server/util/compare-objectId';
 
 import { ObjectIdLike } from '../interfaces/mongoose-utils';
@@ -493,12 +493,14 @@ class PageGrantService {
       [PageGrant.GRANT_RESTRICTED]: null, // any page can be restricted
     };
 
+    const userPossessedGroups = await this.getUserPossessedGroups(user);
+
     // -- Any grant is allowed if parent is null
     const isAnyGrantApplicable = page.parent == null;
     if (isAnyGrantApplicable) {
       data[PageGrant.GRANT_PUBLIC] = null;
       data[PageGrant.GRANT_OWNER] = null;
-      data[PageGrant.GRANT_USER_GROUP] = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user);
+      data[PageGrant.GRANT_USER_GROUP] = { applicableGroups: userPossessedGroups };
       return data;
     }
 
@@ -514,7 +516,7 @@ class PageGrantService {
     if (grant === PageGrant.GRANT_PUBLIC) {
       data[PageGrant.GRANT_PUBLIC] = null;
       data[PageGrant.GRANT_OWNER] = null;
-      data[PageGrant.GRANT_USER_GROUP] = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user);
+      data[PageGrant.GRANT_USER_GROUP] = { applicableGroups: userPossessedGroups };
     }
     else if (grant === PageGrant.GRANT_OWNER) {
       const grantedUser = grantedUsers[0];
@@ -533,14 +535,6 @@ class PageGrantService {
         throw Error('Group not found to calculate grant data.');
       }
 
-      const applicableUserGroups = (await Promise.all(targetUserGroups.map((group) => {
-        return UserGroupRelation.findGroupsWithDescendantsByGroupAndUser(group, user);
-      }))).flat();
-      const applicableExternalUserGroups = (await Promise.all(targetExternalUserGroups.map((group) => {
-        return ExternalUserGroupRelation.findGroupsWithDescendantsByGroupAndUser(group, user);
-      }))).flat();
-      const applicableGroups = [...applicableUserGroups, ...applicableExternalUserGroups];
-
       const isUserExistInUserGroup = (await Promise.all(targetUserGroups.map((group) => {
         return UserGroupRelation.countByGroupIdsAndUser([group._id], user);
       }))).some(count => count > 0);
@@ -552,12 +546,43 @@ class PageGrantService {
       if (isUserExistInGroup) {
         data[PageGrant.GRANT_OWNER] = null;
       }
+
+      const applicableUserGroups = (await Promise.all(targetUserGroups.map((group) => {
+        return UserGroupRelation.findGroupsWithDescendantsByGroupAndUser(group, user);
+      }))).flat();
+      const applicableExternalUserGroups = (await Promise.all(targetExternalUserGroups.map((group) => {
+        return ExternalUserGroupRelation.findGroupsWithDescendantsByGroupAndUser(group, user);
+      }))).flat();
+
+      const applicableGroups = [
+        ...(applicableUserGroups.map((group) => {
+          return { type: GroupType.userGroup, item: group };
+        })),
+        ...(applicableExternalUserGroups.map((group) => {
+          return { type: GroupType.externalUserGroup, item: group };
+        })),
+      ];
       data[PageGrant.GRANT_USER_GROUP] = { applicableGroups };
     }
 
     return data;
   }
 
+  async getUserPossessedGroups(user): Promise<{type: GroupType, item: UserGroupDocument | ExternalUserGroupDocument}[]> {
+    const userPossessedUserGroupIds = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user);
+    const userPossessedExternalUserGroupIds = await ExternalUserGroupRelation.findAllUserGroupIdsRelatedToUser(user);
+    const userPossessedUserGroups = await UserGroup.find({ _id: { $in: userPossessedUserGroupIds } });
+    const userPossessedExternalUserGroups = await ExternalUserGroup.find({ _id: { $in: userPossessedExternalUserGroupIds } });
+    return [
+      ...(userPossessedUserGroups.map((group) => {
+        return { type: GroupType.userGroup, item: group };
+      })),
+      ...(userPossessedExternalUserGroups.map((group) => {
+        return { type: GroupType.externalUserGroup, item: group };
+      })),
+    ];
+  }
+
   /**
    * see: https://dev.growi.org/635a314eac6bcd85cbf359fc
    * @param {string} targetPath

+ 25 - 10
apps/app/test/integration/service/page-grant.test.js

@@ -1,4 +1,4 @@
-import { PageGrant } from '@growi/core';
+import { GroupType, PageGrant } from '@growi/core';
 import mongoose from 'mongoose';
 
 import UserGroup from '~/server/models/user-group';
@@ -490,7 +490,13 @@ describe('PageGrantService', () => {
 
     // parent property of all private pages is null
     test('Any grant is allowed if parent is null', async() => {
-      const userGroupRelation = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user1);
+      const userPossessedUserGroupIds = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user1);
+      const userPossessedUserGroups = await UserGroup.find({ _id: { $in: userPossessedUserGroupIds } });
+      const userPossessedGroups = [
+        ...(userPossessedUserGroups.map((group) => {
+          return { type: GroupType.userGroup, item: group };
+        })),
+      ];
 
       // OnlyMe
       const rootOnlyMePage = await Page.findOne({ path: v4PageRootOnlyMePagePath });
@@ -500,7 +506,7 @@ describe('PageGrantService', () => {
           [PageGrant.GRANT_PUBLIC]: null,
           [PageGrant.GRANT_RESTRICTED]: null,
           [PageGrant.GRANT_OWNER]: null,
-          [PageGrant.GRANT_USER_GROUP]: userGroupRelation,
+          [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userPossessedGroups },
         },
       );
 
@@ -512,7 +518,7 @@ describe('PageGrantService', () => {
           [PageGrant.GRANT_PUBLIC]: null,
           [PageGrant.GRANT_RESTRICTED]: null,
           [PageGrant.GRANT_OWNER]: null,
-          [PageGrant.GRANT_USER_GROUP]: userGroupRelation,
+          [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userPossessedGroups },
         },
       );
 
@@ -524,14 +530,20 @@ describe('PageGrantService', () => {
           [PageGrant.GRANT_PUBLIC]: null,
           [PageGrant.GRANT_RESTRICTED]: null,
           [PageGrant.GRANT_OWNER]: null,
-          [PageGrant.GRANT_USER_GROUP]: userGroupRelation,
+          [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userPossessedGroups },
         },
       );
     });
 
 
     test('Any grant is allowed if parent is public', async() => {
-      const userGroupRelation = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user1);
+      const userPossessedUserGroupIds = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user1);
+      const userPossessedUserGroups = await UserGroup.find({ _id: { $in: userPossessedUserGroupIds } });
+      const userPossessedGroups = [
+        ...(userPossessedUserGroups.map((group) => {
+          return { type: GroupType.userGroup, item: group };
+        })),
+      ];
 
       // OnlyMe
       const publicOnlyMePage = await Page.findOne({ path: pagePublicOnlyMePath });
@@ -541,7 +553,7 @@ describe('PageGrantService', () => {
           [PageGrant.GRANT_PUBLIC]: null,
           [PageGrant.GRANT_RESTRICTED]: null,
           [PageGrant.GRANT_OWNER]: null,
-          [PageGrant.GRANT_USER_GROUP]: userGroupRelation,
+          [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userPossessedGroups },
         },
       );
 
@@ -553,7 +565,7 @@ describe('PageGrantService', () => {
           [PageGrant.GRANT_PUBLIC]: null,
           [PageGrant.GRANT_RESTRICTED]: null,
           [PageGrant.GRANT_OWNER]: null,
-          [PageGrant.GRANT_USER_GROUP]: userGroupRelation,
+          [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userPossessedGroups },
         },
       );
 
@@ -565,7 +577,7 @@ describe('PageGrantService', () => {
           [PageGrant.GRANT_PUBLIC]: null,
           [PageGrant.GRANT_RESTRICTED]: null,
           [PageGrant.GRANT_OWNER]: null,
-          [PageGrant.GRANT_USER_GROUP]: userGroupRelation,
+          [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userPossessedGroups },
         },
       );
     });
@@ -633,7 +645,10 @@ describe('PageGrantService', () => {
     });
 
     test('"GRANT_USER_GROUP" is allowed if the parent\'s grant is GRANT_USER_GROUP and the user is included in the group', async() => {
-      const applicableGroups = await UserGroupRelation.findGroupsWithDescendantsByGroupAndUser(groupParent, user1);
+      const userGroups = await UserGroupRelation.findGroupsWithDescendantsByGroupAndUser(groupParent, user1);
+      const applicableGroups = userGroups.map((group) => {
+        return { type: GroupType.userGroup, item: group };
+      });
 
       // Public
       const onlyInsideGroupPublicPage = await Page.findOne({ path: pageOnlyInsideTheGroupPublicPath });