fix: permission (#3374)

* fix: permission

* feat: create dataset per
This commit is contained in:
Archer
2024-12-11 20:56:52 +08:00
committed by GitHub
parent 8a4715293e
commit c0135f5f21
4 changed files with 95 additions and 55 deletions

View File

@@ -35,12 +35,12 @@ async function handler(req: ApiRequestProps<CreateAppBody>) {
} }
// 凭证校验 // 凭证校验
const { teamId, tmbId } = await authUserPer({ req, authToken: true, per: WritePermissionVal }); const [{ teamId, tmbId }] = await Promise.all([
if (parentId) { authUserPer({ req, authToken: true, per: WritePermissionVal }),
// if it is not a root app ...(parentId
// check the parent folder permission ? [authApp({ req, appId: parentId, per: WritePermissionVal, authToken: true })]
await authApp({ req, appId: parentId, per: WritePermissionVal, authToken: true }); : [])
} ]);
// 上限校验 // 上限校验
await checkTeamAppLimit(teamId); await checkTeamAppLimit(teamId);

View File

@@ -25,6 +25,16 @@ export type ListAppBody = {
searchKey?: string; searchKey?: string;
}; };
/*
获取 APP 列表权限
1. 校验 folder 权限和获取 team 权限owner 单独处理)
2. 获取 team 下所有 app 权限。获取我的所有组。并计算出我所有的app权限。
3. 过滤我有的权限的 app以及当前 parentId 的 app由于权限继承问题这里没法一次性根据 id 去获取)
4. 根据过滤条件获取 app 列表
5. 遍历搜索出来的 app并赋予权限继承的 app使用 parent 的权限)
6. 再根据 read 权限进行一次过滤。
*/
async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemType[]> { async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemType[]> {
const { parentId, type, getRecentlyChat, searchKey } = req.body; const { parentId, type, getRecentlyChat, searchKey } = req.body;
@@ -75,6 +85,24 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
); );
const findAppsQuery = (() => { const findAppsQuery = (() => {
if (getRecentlyChat) {
return {
// get all chat app
teamId,
type: { $in: [AppTypeEnum.workflow, AppTypeEnum.simple, AppTypeEnum.plugin] }
};
}
// Filter apps by permission, if not owner, only get apps that I have permission to access
const idList = { _id: { $in: myPerList.map((item) => item.resourceId) } };
const appPerQuery = teamPer.isOwner
? {}
: parentId
? {
$or: [idList, parseParentIdInMongo(parentId)]
}
: idList;
const searchMatch = searchKey const searchMatch = searchKey
? { ? {
$or: [ $or: [
@@ -83,31 +111,17 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
] ]
} }
: {}; : {};
// Filter apps by permission, if not owner, only get apps that I have permission to access
const appIdQuery = teamPer.isOwner
? {}
: { _id: { $in: myPerList.map((item) => item.resourceId) } };
if (getRecentlyChat) {
return {
// get all chat app
...appIdQuery,
teamId,
type: { $in: [AppTypeEnum.workflow, AppTypeEnum.simple, AppTypeEnum.plugin] },
...searchMatch
};
}
if (searchKey) { if (searchKey) {
return { return {
...appIdQuery, ...appPerQuery,
teamId, teamId,
...searchMatch ...searchMatch
}; };
} }
return { return {
...appIdQuery, ...appPerQuery,
teamId, teamId,
...(type && (Array.isArray(type) ? { type: { $in: type } } : { type })), ...(type && (Array.isArray(type) ? { type: { $in: type } } : { type })),
...parseParentIdInMongo(parentId) ...parseParentIdInMongo(parentId)
@@ -144,7 +158,9 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
); );
// Count app collaborators // Count app collaborators
const clbCount = perList.filter((item) => String(item.resourceId) === appId).length; const clbCount = perList.filter(
(item) => String(item.resourceId) === String(app._id)
).length;
return { return {
Per: new AppPermission({ Per: new AppPermission({
@@ -156,8 +172,8 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
}; };
// Inherit app // Inherit app
if (app.inheritPermission && parentId && !AppFolderTypeList.includes(app.type)) { if (app.inheritPermission && app.parentId && !AppFolderTypeList.includes(app.type)) {
return getPer(String(parentId)); return getPer(String(app.parentId));
} else { } else {
return getPer(String(app._id)); return getPer(String(app._id));
} }

View File

@@ -9,6 +9,7 @@ import { NextAPI } from '@/service/middleware/entry';
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset'; import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
import type { ApiRequestProps } from '@fastgpt/service/type/next'; import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils'; import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
export type DatasetCreateQuery = {}; export type DatasetCreateQuery = {};
export type DatasetCreateBody = CreateDatasetParams; export type DatasetCreateBody = CreateDatasetParams;
@@ -29,12 +30,25 @@ async function handler(
} = req.body; } = req.body;
// auth // auth
const { teamId, tmbId } = await authUserPer({ const [{ teamId, tmbId }] = await Promise.all([
req, authUserPer({
authToken: true, req,
authApiKey: true, authToken: true,
per: WritePermissionVal authApiKey: true,
}); per: WritePermissionVal
}),
...(parentId
? [
authDataset({
req,
datasetId: parentId,
authToken: true,
authApiKey: true,
per: WritePermissionVal
})
]
: [])
]);
// check model valid // check model valid
const vectorModelStore = getVectorModel(vectorModel); const vectorModelStore = getVectorModel(vectorModel);

View File

@@ -74,6 +74,16 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
); );
const findDatasetQuery = (() => { const findDatasetQuery = (() => {
// Filter apps by permission, if not owner, only get apps that I have permission to access
const idList = { _id: { $in: myPerList.map((item) => item.resourceId) } };
const datasetPerQuery = teamPer.isOwner
? {}
: parentId
? {
$or: [idList, parseParentIdInMongo(parentId)]
}
: idList;
const searchMatch = searchKey const searchMatch = searchKey
? { ? {
$or: [ $or: [
@@ -82,21 +92,17 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
] ]
} }
: {}; : {};
// Filter apps by permission, if not owner, only get apps that I have permission to access
const appIdQuery = teamPer.isOwner
? {}
: { _id: { $in: myPerList.map((item) => item.resourceId) } };
if (searchKey) { if (searchKey) {
return { return {
...appIdQuery, ...datasetPerQuery,
teamId, teamId,
...searchMatch ...searchMatch
}; };
} }
return { return {
...appIdQuery, ...datasetPerQuery,
teamId, teamId,
...(type ? (Array.isArray(type) ? { type: { $in: type } } : { type }) : {}), ...(type ? (Array.isArray(type) ? { type: { $in: type } } : { type }) : {}),
...parseParentIdInMongo(parentId) ...parseParentIdInMongo(parentId)
@@ -122,7 +128,9 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
.map((item) => item.permission) .map((item) => item.permission)
); );
const clbCount = perList.filter((item) => String(item.resourceId) === datasetId).length; const clbCount = perList.filter(
(item) => String(item.resourceId) === String(dataset._id)
).length;
return { return {
Per: new DatasetPermission({ Per: new DatasetPermission({
@@ -133,8 +141,12 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
}; };
}; };
// inherit // inherit
if (dataset.inheritPermission && parentId && dataset.type !== DatasetTypeEnum.folder) { if (
return getPer(String(parentId)); dataset.inheritPermission &&
dataset.parentId &&
dataset.type !== DatasetTypeEnum.folder
) {
return getPer(String(dataset.parentId));
} else { } else {
return getPer(String(dataset._id)); return getPer(String(dataset._id));
} }
@@ -148,21 +160,19 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
}) })
.filter((app) => app.permission.hasReadPer); .filter((app) => app.permission.hasReadPer);
const data = await Promise.all( const data = formatDatasets.map<DatasetListItemType>((item) => ({
formatDatasets.map<DatasetListItemType>((item) => ({ _id: item._id,
_id: item._id, avatar: item.avatar,
avatar: item.avatar, name: item.name,
name: item.name, intro: item.intro,
intro: item.intro, type: item.type,
type: item.type, permission: item.permission,
permission: item.permission, vectorModel: getVectorModel(item.vectorModel),
vectorModel: getVectorModel(item.vectorModel), inheritPermission: item.inheritPermission,
inheritPermission: item.inheritPermission, tmbId: item.tmbId,
tmbId: item.tmbId, updateTime: item.updateTime,
updateTime: item.updateTime, private: item.privateDataset
private: item.privateDataset }));
}))
);
return data; return data;
} }