dataset inheritance permission (#2151)

* refactor: dataset create and update api

* chore: defaultpermission & resume fe

* refactor: database auth

* fix(ts): add inheritPermission into default data types

* chore: adjust the code

* fix: list api type filter

* fix: query condition
This commit is contained in:
Finley Ge
2024-07-25 19:03:24 +08:00
committed by GitHub
parent 5906daff9f
commit 65515e7952
20 changed files with 481 additions and 199 deletions

View File

@@ -8,8 +8,8 @@ export enum DatasetErrEnum {
unAuthDatasetCollection = 'unAuthDatasetCollection',
unAuthDatasetData = 'unAuthDatasetData',
unAuthDatasetFile = 'unAuthDatasetFile',
unLinkCollection = 'unLinkCollection'
unLinkCollection = 'unLinkCollection',
invalidVectorModelOrQAModel = 'invalidVectorModelOrQAModel'
}
const datasetErr = [
{
@@ -39,6 +39,10 @@ const datasetErr = [
{
statusText: DatasetErrEnum.unLinkCollection,
message: 'core.dataset.error.unLinkCollection'
},
{
statusText: DatasetErrEnum.invalidVectorModelOrQAModel,
message: 'core.dataset.error.invalidVectorModelOrQAModel'
}
];
export default datasetErr.reduce((acc, cur, index) => {

View File

@@ -10,7 +10,6 @@ export type DatasetUpdateBody = {
name?: string;
avatar?: string;
intro?: string;
permission?: DatasetSchemaType['permission']; // TODO: Should be deleted.
agentModel?: LLMModelItemType;
status?: DatasetSchemaType['status'];

View File

@@ -1,4 +1,4 @@
import { PermissionValueType } from 'support/permission/type';
import { PermissionSchemaType } from '../../support/permission/type';
import type { LLMModelItemType, VectorModelItemType } from '../../core/ai/model.d';
import { PermissionTypeEnum } from '../../support/permission/constant';
import { PushDatasetDataChunkProps } from './api';
@@ -12,31 +12,28 @@ import {
import { DatasetPermission } from '../../support/permission/dataset/controller';
import { Permission } from '../../support/permission/controller';
/* schema */
export type DatasetSchemaType = {
_id: string;
parentId: string;
parentId?: string;
userId: string;
teamId: string;
tmbId: string;
updateTime: Date;
avatar: string;
name: string;
vectorModel: string;
agentModel: string;
intro: string;
type: DatasetTypeEnum;
type: `${DatasetTypeEnum}`;
status: `${DatasetStatusEnum}`;
// permission: DatasetPermission;
// metadata
websiteConfig?: {
url: string;
selector: string;
};
externalReadUrl?: string;
defaultPermission: PermissionValueType;
};
} & PermissionSchemaType;
// } & PermissionSchemaType;
export type DatasetCollectionSchemaType = {
_id: string;
@@ -133,15 +130,13 @@ export type DatasetSimpleItemType = {
};
export type DatasetListItemType = {
_id: string;
parentId: string;
avatar: string;
name: string;
intro: string;
type: DatasetTypeEnum;
type: `${DatasetTypeEnum}`;
permission: DatasetPermission;
vectorModel: VectorModelItemType;
defaultPermission: PermissionValueType;
};
} & PermissionSchemaType;
export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel'> & {
vectorModel: VectorModelItemType;

View File

@@ -1,6 +1,4 @@
import { connectionMongo, getMongoModel, type Model } from '../../common/mongo';
const { Schema, model, models } = connectionMongo;
import { DatasetSchemaType } from '@fastgpt/global/core/dataset/type.d';
import { getMongoModel, Schema } from '../../common/mongo';
import {
DatasetStatusEnum,
DatasetStatusMap,
@@ -12,6 +10,8 @@ import {
TeamMemberCollectionName
} from '@fastgpt/global/support/user/team/constant';
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
import { getPermissionSchema } from '@fastgpt/global/support/permission/utils';
import type { DatasetSchemaType } from '@fastgpt/global/core/dataset/type.d';
export const DatasetCollectionName = 'datasets';
@@ -85,11 +85,10 @@ const DatasetSchema = new Schema({
}
}
},
externalReadUrl: String,
defaultPermission: {
type: Number,
default: DatasetDefaultPermissionVal
}
externalReadUrl: {
type: String
},
...getPermissionSchema(DatasetDefaultPermissionVal)
});
try {

View File

@@ -17,10 +17,11 @@ import { getFileById } from '../../../common/file/gridfs/controller';
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { MongoDatasetData } from '../../../core/dataset/data/schema';
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
import { AuthModeType, AuthResponseType } from '../type';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
export async function authDatasetByTmbId({
export const authDatasetByTmbId = async ({
tmbId,
datasetId,
per
@@ -28,30 +29,64 @@ export async function authDatasetByTmbId({
tmbId: string;
datasetId: string;
per: PermissionValueType;
}) {
const { teamId, permission: tmbPer } = await getTmbInfoByTmbId({ tmbId });
}): Promise<{
dataset: DatasetSchemaType & {
permission: DatasetPermission;
};
}> => {
const dataset = await (async () => {
// get app and per
const [dataset, rp] = await Promise.all([
MongoDataset.findOne({ _id: datasetId, teamId }).lean(),
getResourcePermission({
teamId,
tmbId,
resourceId: datasetId,
resourceType: PerResourceTypeEnum.dataset
}) // this could be null
const [{ teamId, permission: tmbPer }, dataset] = await Promise.all([
getTmbInfoByTmbId({ tmbId }),
MongoDataset.findOne({ _id: datasetId }).lean()
]);
if (!dataset) {
return Promise.reject(DatasetErrEnum.unExist);
}
const isOwner = tmbPer.isOwner || String(dataset.tmbId) === String(tmbId);
const Per = new DatasetPermission({
per: rp?.permission ?? dataset.defaultPermission,
isOwner
});
// get dataset permission or inherit permission from parent folder.
const { Per, defaultPermission } = await (async () => {
if (
dataset.type === DatasetTypeEnum.folder ||
dataset.inheritPermission === false ||
!dataset.parentId
) {
// 1. is a folder. (Folders have compeletely permission)
// 2. inheritPermission is false.
// 3. is root folder/dataset.
const rp = await getResourcePermission({
teamId,
tmbId,
resourceId: datasetId,
resourceType: PerResourceTypeEnum.dataset
});
const Per = new DatasetPermission({
per: rp?.permission ?? dataset.defaultPermission,
isOwner
});
return {
Per,
defaultPermission: dataset.defaultPermission
};
} else {
// is not folder and inheritPermission is true and is not root folder.
const { dataset: parent } = await authDatasetByTmbId({
tmbId,
datasetId: dataset.parentId,
per
});
const Per = new DatasetPermission({
per: parent.permission.value,
isOwner
});
return {
Per,
defaultPermission: parent.defaultPermission
};
}
})();
if (!Per.checkPer(per)) {
return Promise.reject(DatasetErrEnum.unAuthDataset);
@@ -59,27 +94,34 @@ export async function authDatasetByTmbId({
return {
...dataset,
defaultPermission: dataset.defaultPermission ?? DatasetDefaultPermissionVal,
defaultPermission,
permission: Per
};
})();
return { dataset };
}
};
// Auth Dataset
export async function authDataset({
export const authDataset = async ({
datasetId,
per = NullPermission,
per,
...props
}: AuthModeType & {
datasetId: string;
datasetId: ParentIdType;
per: PermissionValueType;
}): Promise<
AuthResponseType<DatasetPermission> & {
dataset: DatasetSchemaType;
AuthResponseType & {
dataset: DatasetSchemaType & {
permission: DatasetPermission;
};
}
> => {
const result = await parseHeaderCert(props);
const { tmbId } = result;
if (!datasetId) {
return Promise.reject(DatasetErrEnum.unExist);
}
> {
const { teamId, tmbId } = await parseHeaderCert(props);
const { dataset } = await authDatasetByTmbId({
tmbId,
@@ -88,13 +130,11 @@ export async function authDataset({
});
return {
teamId,
tmbId,
dataset,
permission: dataset.permission
...result,
permission: dataset.permission,
dataset
};
}
};
// the temporary solution for authDatasetCollection is getting the
export async function authDatasetCollection({
collectionId,

View File

@@ -511,7 +511,8 @@
"unAuthDatasetData": "Unauthorized to operate this data",
"unAuthDatasetFile": "Unauthorized to operate this file",
"unCreateCollection": "Unauthorized to operate this data",
"unLinkCollection": "Not a network link collection"
"unLinkCollection": "Not a network link collection",
"invalidVectorModelOrQAModel": "Invalid vector model or QA model"
},
"externalFile": "external file repository",
"file": "File",

View File

@@ -511,7 +511,8 @@
"unAuthDatasetData": "无权操作该数据",
"unAuthDatasetFile": "无权操作该文件",
"unCreateCollection": "无权操作该数据",
"unLinkCollection": "不是网络链接集合"
"unLinkCollection": "不是网络链接集合",
"invalidVectorModelOrQAModel": "VectorModel 或 QA 模型错误"
},
"externalFile": "外部文件库",
"file": "文件",