Files
FastGPT/packages/service/support/permission/inheritPermission.ts
Archer a9cdece341 4.8.6 merge (#1943)
* Dataset collection forbid (#1885)

* perf: tool call support same id

* feat: collection forbid

* feat: collection forbid

* Inheritance Permission for apps (#1897)

* feat: app schema define

chore: references of authapp

* feat: authApp method inheritance

* feat: create and update api

* feat: update

* feat: inheritance Permission controller for app.

* feat: abstract version of inheritPermission

* feat: ancestorId for apps

* chore: update app

* fix: inheritPermission abstract version

* feat: update folder defaultPermission

* feat: app update api

* chore: inheritance frontend

* chore: app list api

* feat: update defaultPermission in app deatil

* feat: backend api finished

* feat: app inheritance permission fe

* fix: app update defaultpermission causes collaborator miss

* fix: ts error

* chore: adjust the codes

* chore: i18n

chore: i18n

* chore: fe adjust and i18n

* chore: adjust the code

* feat: resume api;
chore: rewrite update api and inheritPermission methods

* chore: something

* chore: fe code adjusting

* feat: frontend adjusting

* chore: fe code adjusting

* chore: adjusting the code

* perf: fe loading

* format

* Inheritance fix (#1908)

* fix: SlideCard

* fix: authapp did not return parent app for inheritance app

* fix: fe adjusting

* feat: fe adjusing

* perf: inherit per ux

* doc

* fix: ts errors (#1916)

* perf: inherit permission

* fix: permission inherit

* Workflow type (#1938)

* perf: workflow type

tmp workflow

perf: workflow type

feat: custom field config

* perf: dynamic input

* perf: node classify

* perf: node classify

* perf: node classify

* perf: node classify

* fix: workflow custom input

* feat: text editor and customFeedback move to basic nodes

* feat: community system plugin

* fix: ts

* feat: exprEval plugin

* perf: workflow type

* perf: plugin important

* fix: default templates

* perf: markdown hr css

* lock

* perf: fetch url

* perf: new plugin version

* fix: chat histories update

* fix: collection paths invalid

* perf: app card ui

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
2024-07-04 17:42:09 +08:00

222 lines
5.5 KiB
TypeScript

import { mongoSessionRun } from '../../common/mongo/sessionRun';
import { MongoResourcePermission } from './schema';
import { ClientSession, Model } from 'mongoose';
import { NullPermission, PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import { getResourceAllClbs } from './controller';
export type SyncChildrenPermissionResourceType = {
_id: string;
type: string;
teamId: string;
parentId?: ParentIdType;
};
export type UpdateCollaboratorItem = {
permission: PermissionValueType;
tmbId: string;
};
// sync the permission to all children folders.
export async function syncChildrenPermission({
resource,
folderTypeList,
resourceType,
resourceModel,
session,
defaultPermission,
collaborators
}: {
resource: SyncChildrenPermissionResourceType;
// when the resource is a folder
folderTypeList: string[];
resourceModel: typeof Model;
resourceType: PerResourceTypeEnum;
// should be provided when inheritPermission is true
session: ClientSession;
defaultPermission?: PermissionValueType;
collaborators?: UpdateCollaboratorItem[];
}) {
// only folder has permission
const isFolder = folderTypeList.includes(resource.type);
if (!isFolder) return;
// get all folders and the resource permission of the app
const allFolders = await resourceModel
.find(
{
teamId: resource.teamId,
type: { $in: folderTypeList },
inheritPermission: true
},
'_id parentId'
)
.lean<SyncChildrenPermissionResourceType[]>()
.session(session);
// bfs to get all children
const queue = [String(resource._id)];
const children: string[] = [];
while (queue.length) {
const parentId = queue.shift();
const folderChildren = allFolders.filter(
(folder) => String(folder.parentId) === String(parentId)
);
children.push(...folderChildren.map((folder) => folder._id));
queue.push(...folderChildren.map((folder) => folder._id));
}
if (!children.length) return;
// Sync default permission
if (defaultPermission !== undefined) {
await resourceModel.updateMany(
{
_id: { $in: children }
},
{
defaultPermission
},
{ session }
);
}
// sync the resource permission
if (collaborators) {
// Update the collaborators of all children
for await (const childId of children) {
await syncCollaborators({
resourceType,
session,
collaborators,
teamId: resource.teamId,
resourceId: childId
});
}
}
}
/* Resume the inherit permission of the resource.
1. Folder: Sync parent's defaultPermission and clbs, and sync its children.
2. Resource: Sync parent's defaultPermission, and delete all its clbs.
*/
export async function resumeInheritPermission({
resource,
folderTypeList,
resourceType,
resourceModel,
session
}: {
resource: SyncChildrenPermissionResourceType;
folderTypeList: string[];
resourceType: PerResourceTypeEnum;
resourceModel: typeof Model;
session?: ClientSession;
}) {
const isFolder = folderTypeList.includes(resource.type);
const fn = async (session: ClientSession) => {
const parentResource = await resourceModel
.findById(resource.parentId, 'defaultPermission')
.lean<SyncChildrenPermissionResourceType & { defaultPermission: PermissionValueType }>()
.session(session);
const parentDefaultPermissionVal = parentResource?.defaultPermission ?? NullPermission;
// update the resource permission
await resourceModel.updateOne(
{
_id: resource._id
},
{
inheritPermission: true,
defaultPermission: parentDefaultPermissionVal
},
{ session }
);
// Folder resource, need to sync children
if (isFolder) {
const parentClbs = await getResourceAllClbs({
resourceId: resource.parentId,
teamId: resource.teamId,
resourceType,
session
});
// sync self
await syncCollaborators({
resourceType,
collaborators: parentClbs,
teamId: resource.teamId,
resourceId: resource._id,
session
});
// sync children
await syncChildrenPermission({
resource: {
...resource
},
resourceModel,
folderTypeList,
resourceType,
session,
defaultPermission: parentDefaultPermissionVal,
collaborators: parentClbs
});
} else {
// Not folder, delete all clb
await MongoResourcePermission.deleteMany({ resourceId: resource._id }, { session });
}
};
if (session) {
return fn(session);
} else {
return mongoSessionRun(fn);
}
}
/*
Delete all the collaborators and then insert the new collaborators.
*/
export async function syncCollaborators({
resourceType,
teamId,
resourceId,
collaborators,
session
}: {
resourceType: PerResourceTypeEnum;
teamId: string;
resourceId: string;
collaborators: UpdateCollaboratorItem[];
session: ClientSession;
}) {
await MongoResourcePermission.deleteMany(
{
resourceType,
teamId,
resourceId
},
{ session }
);
await MongoResourcePermission.insertMany(
collaborators.map((item) => ({
teamId: teamId,
resourceId,
resourceType: resourceType,
tmbId: item.tmbId,
permission: item.permission
})),
{
session
}
);
}