Sfoglia il codice sorgente

resolve conflicts cherry picking f8c65e5c29

Taichi Masuyama 3 anni fa
parent
commit
e570ccfe50

+ 10 - 1
packages/app/src/server/models/page.ts

@@ -1032,7 +1032,7 @@ export default (crowi): any => {
       let isGrantNormalized = false;
       try {
         // TODO: fix
-        const shouldCheckDescendants = options.overwriteScopesOfDescendants !== true;
+        const shouldCheckDescendants = !options.overwriteScopesOfDescendants;
         isGrantNormalized = await pageGrantService.isGrantNormalized(user, pageData.path, grant, grantedUserIds, grantUserGroupId, shouldCheckDescendants);
       }
       catch (err) {
@@ -1043,6 +1043,15 @@ export default (crowi): any => {
         throw Error('The selected grant or grantedGroup is not assignable to this page.');
       }
 
+      if (options.overwriteScopesOfDescendants) {
+        const updateGrantInfo = await pageGrantService.generateUpdateGrantInfo(user, grant, options.grantUserGroupId);
+        const canOverwriteDescendants = await pageGrantService.canOverwriteDescendants(pageData, user, updateGrantInfo);
+
+        if (!canOverwriteDescendants) {
+          throw Error('Cannot overwrite scopes of descendants.');
+        }
+      }
+
       if (!wasOnTree) {
         const newParent = await pageService.getParentAndFillAncestorsByUser(user, newPageData.path);
         newPageData.parent = newParent._id;

+ 9 - 0
packages/app/src/server/models/user-group-relation.js

@@ -93,6 +93,15 @@ class UserGroupRelation {
       .exec();
   }
 
+  static async findAllUserIdsForUserGroup(userGroup) {
+    const relations = await this
+      .find({ relatedGroup: userGroup })
+      .select('relatedUser')
+      .exec();
+
+    return relations.map(r => r.relatedUser);
+  }
+
   /**
    * find all user and group relation of UserGroups
    *

+ 37 - 1
packages/app/src/server/service/page-grant.ts

@@ -2,7 +2,7 @@ import { pagePathUtils, pathUtils, pageUtils } from '@growi/core';
 import escapeStringRegexp from 'escape-string-regexp';
 import mongoose from 'mongoose';
 
-import { PageGrant } from '~/interfaces/page';
+import { PageGrant, PageGrantCanBeOnTree } from '~/interfaces/page';
 import { IRecordApplicableGrant } from '~/interfaces/page-grant';
 import { PageDocument, PageModel } from '~/server/models/page';
 import UserGroup from '~/server/models/user-group';
@@ -540,6 +540,42 @@ class PageGrantService {
     return this.calcCanOverwriteDescendants(operatorGrantInfo, updateGrantInfo, descendantPagesGrantInfo);
   }
 
+  async generateUpdateGrantInfo(operator, updateGrant: PageGrantCanBeOnTree, grantUserGroupId?: ObjectIdLike): Promise<UpdateGrantInfo> {
+    let updateGrantInfo: UpdateGrantInfo | null = null;
+
+    if (updateGrant === PageGrant.GRANT_PUBLIC) {
+      updateGrantInfo = {
+        grant: PageGrant.GRANT_PUBLIC,
+      };
+    }
+    else if (updateGrant === PageGrant.GRANT_OWNER) {
+      updateGrantInfo = {
+        grant: PageGrant.GRANT_OWNER,
+        grantedUserId: operator._id,
+      };
+    }
+    else if (updateGrant === PageGrant.GRANT_USER_GROUP) {
+      if (grantUserGroupId == null) {
+        throw Error('The parameter `grantUserGroupId` is required.');
+      }
+      const userIds = await UserGroup.findAllUserIdsForUserGroup(grantUserGroupId);
+      updateGrantInfo = {
+        grant: PageGrant.GRANT_USER_GROUP,
+        grantedUserGroupInfo: {
+          groupId: grantUserGroupId,
+          userIds: new Set<ObjectIdLike>(userIds),
+          childrenOrItselfGroupIds: new Set<ObjectIdLike>(),
+        },
+      };
+    }
+
+    if (updateGrantInfo == null) {
+      throw Error('The parameter `updateGrant` must be 1, 4, or 5');
+    }
+
+    return updateGrantInfo;
+  }
+
   private calcIsAllDescendantsGrantedByOperator(operatorGrantInfo: OperatorGrantInfo, descendantPagesGrantInfo: DescendantPagesGrantInfo): boolean {
     if (descendantPagesGrantInfo.grantSet.has(PageGrant.GRANT_OWNER)) {
       const isNonApplicableOwnerExist = descendantPagesGrantInfo.grantedUserIds.size >= 2

+ 3 - 1
packages/core/src/interfaces/page.ts

@@ -54,7 +54,9 @@ export const PageGrant = {
   GRANT_OWNER: 4,
   GRANT_USER_GROUP: 5,
 } as const;
-export type PageGrant = typeof PageGrant[keyof typeof PageGrant];
+type UnionPageGrantKeys = keyof typeof PageGrant;
+export type PageGrant = typeof PageGrant[UnionPageGrantKeys];
+export type PageGrantCanBeOnTree = typeof PageGrant[Exclude<UnionPageGrantKeys, 'GRANT_RESTRICTED' | 'GRANT_SPECIFIED'>];
 
 export type IPageHasId = IPage & HasObjectId;