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

View File

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

View File

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

View File

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

View File

@@ -511,7 +511,8 @@
"unAuthDatasetData": "Unauthorized to operate this data", "unAuthDatasetData": "Unauthorized to operate this data",
"unAuthDatasetFile": "Unauthorized to operate this file", "unAuthDatasetFile": "Unauthorized to operate this file",
"unCreateCollection": "Unauthorized to operate this data", "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", "externalFile": "external file repository",
"file": "File", "file": "File",

View File

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

View File

@@ -5,7 +5,7 @@ import React from 'react';
import { DatasetTypeMap } from '@fastgpt/global/core/dataset/constants'; import { DatasetTypeMap } from '@fastgpt/global/core/dataset/constants';
import { useI18n } from '@/web/context/I18n'; import { useI18n } from '@/web/context/I18n';
const DatasetTypeTag = ({ type, ...props }: { type: DatasetTypeEnum } & FlexProps) => { const DatasetTypeTag = ({ type, ...props }: { type: `${DatasetTypeEnum}` } & FlexProps) => {
const { datasetT } = useI18n(); const { datasetT } = useI18n();
const item = DatasetTypeMap[type] || DatasetTypeMap['dataset']; const item = DatasetTypeMap[type] || DatasetTypeMap['dataset'];

View File

@@ -25,7 +25,6 @@ export type CreateDatasetParams = {
avatar: string; avatar: string;
vectorModel?: string; vectorModel?: string;
agentModel?: string; agentModel?: string;
defaultPermission?: PermissionValueType;
}; };
export type RebuildEmbeddingProps = { export type RebuildEmbeddingProps = {

View File

@@ -1,23 +1,30 @@
import type { NextApiRequest } from 'next';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema'; import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import type { CreateDatasetParams } from '@/global/core/dataset/api.d'; import type { CreateDatasetParams } from '@/global/core/dataset/api.d';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth'; import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { getLLMModel, getVectorModel, getDatasetModel } from '@fastgpt/service/core/ai/model'; import { getLLMModel, getVectorModel, getDatasetModel } from '@fastgpt/service/core/ai/model';
import { checkTeamDatasetLimit } from '@fastgpt/service/support/permission/teamLimit'; import { checkTeamDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
import { NullPermission, WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
async function handler(req: NextApiRequest) { export type DatasetCreateQuery = {};
export type DatasetCreateBody = CreateDatasetParams;
export type DatasetCreateResponse = string;
async function handler(
req: ApiRequestProps<DatasetCreateBody, DatasetCreateQuery>
): Promise<DatasetCreateResponse> {
const { const {
parentId, parentId,
name, name,
type = DatasetTypeEnum.dataset, type = DatasetTypeEnum.dataset,
avatar, avatar,
vectorModel = global.vectorModels[0].model, vectorModel = global.vectorModels[0].model,
agentModel = getDatasetModel().model, agentModel = getDatasetModel().model
defaultPermission = NullPermission } = req.body;
} = req.body as CreateDatasetParams;
// auth // auth
const { teamId, tmbId } = await authUserPer({ const { teamId, tmbId } = await authUserPer({
@@ -31,25 +38,23 @@ async function handler(req: NextApiRequest) {
const vectorModelStore = getVectorModel(vectorModel); const vectorModelStore = getVectorModel(vectorModel);
const agentModelStore = getLLMModel(agentModel); const agentModelStore = getLLMModel(agentModel);
if (!vectorModelStore || !agentModelStore) { if (!vectorModelStore || !agentModelStore) {
throw new Error('vectorModel or qaModel is invalid'); // TODO: use enum code return Promise.reject(DatasetErrEnum.invalidVectorModelOrQAModel);
} }
// check limit // check limit
await checkTeamDatasetLimit(teamId); await checkTeamDatasetLimit(teamId);
const { _id } = await MongoDataset.create({ const { _id } = await MongoDataset.create({
...parseParentIdInMongo(parentId),
name, name,
teamId, teamId,
tmbId, tmbId,
vectorModel, vectorModel,
agentModel, agentModel,
avatar, avatar,
parentId: parentId || null, type
type,
defaultPermission
}); });
return _id; return _id;
} }
export default NextAPI(handler); export default NextAPI(handler);

View File

@@ -1,4 +1,3 @@
import type { NextApiRequest } from 'next';
import type { DatasetListItemType } from '@fastgpt/global/core/dataset/type.d'; import type { DatasetListItemType } from '@fastgpt/global/core/dataset/type.d';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema'; import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
@@ -14,29 +13,70 @@ import { MongoResourcePermission } from '@fastgpt/service/support/permission/sch
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant'; import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type'; import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils'; import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
import { ApiRequestProps } from '@fastgpt/service/type/next';
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
export type GetDatasetListBody = { parentId: ParentIdType; type?: DatasetTypeEnum }; export type GetDatasetListBody = {
parentId: ParentIdType;
type?: DatasetTypeEnum;
searchKey?: string;
};
async function handler(req: NextApiRequest) { async function handler(req: ApiRequestProps<GetDatasetListBody>) {
const { parentId, type } = req.body as GetDatasetListBody; const { parentId, type, searchKey } = req.body;
// 凭证校验 // 凭证校验
const { const {
dataset: parentDataset,
teamId, teamId,
tmbId, tmbId,
permission: tmbPer permission: tmbPer
} = await authUserPer({ } = await (async () => {
req, if (parentId) {
authToken: true, return await authDataset({
authApiKey: true, req,
per: ReadPermissionVal authToken: true,
}); per: ReadPermissionVal,
datasetId: parentId
});
}
return {
...(await authUserPer({
req,
authToken: true,
authApiKey: true,
per: ReadPermissionVal
})),
dataset: undefined
};
})();
const findDatasetQuery = (() => {
const searchMatch = searchKey
? {
$or: [
{ name: { $regex: new RegExp(`${replaceRegChars(searchKey)}`, 'i') } },
{ intro: { $regex: new RegExp(`${replaceRegChars(searchKey)}`, 'i') } }
]
}
: {};
if (searchKey) {
return {
teamId,
...searchMatch
};
}
return {
teamId,
...(type ? (Array.isArray(type) ? { type: { $in: type } } : { type }) : {}),
...parseParentIdInMongo(parentId)
};
})();
const [myDatasets, rpList] = await Promise.all([ const [myDatasets, rpList] = await Promise.all([
MongoDataset.find({ MongoDataset.find(findDatasetQuery)
teamId,
...parseParentIdInMongo(parentId),
...(type && { type })
})
.sort({ .sort({
updateTime: -1 updateTime: -1
}) })
@@ -50,14 +90,26 @@ async function handler(req: NextApiRequest) {
const filterDatasets = myDatasets const filterDatasets = myDatasets
.map((dataset) => { .map((dataset) => {
const perVal = rpList.find( const Per = (() => {
(item) => String(item.resourceId) === String(dataset._id) if (dataset.inheritPermission && parentDataset && dataset.type !== DatasetTypeEnum.folder) {
)?.permission; dataset.defaultPermission = parentDataset.defaultPermission;
const Per = new DatasetPermission({ const perVal = rpList.find(
per: perVal ?? dataset.defaultPermission, (item) => String(item.resourceId) === String(parentDataset._id)
isOwner: String(dataset.tmbId) === tmbId || tmbPer.isOwner )?.permission;
}); return new DatasetPermission({
per: perVal ?? parentDataset.defaultPermission,
isOwner: String(parentDataset.tmbId) === tmbId || tmbPer.isOwner
});
} else {
const perVal = rpList.find(
(item) => String(item.resourceId) === String(dataset._id)
)?.permission;
return new DatasetPermission({
per: perVal ?? dataset.defaultPermission,
isOwner: String(dataset.tmbId) === tmbId || tmbPer.isOwner
});
}
})();
return { return {
...dataset, ...dataset,
permission: Per permission: Per
@@ -68,14 +120,14 @@ async function handler(req: NextApiRequest) {
const data = await Promise.all( const data = await Promise.all(
filterDatasets.map<DatasetListItemType>((item) => ({ filterDatasets.map<DatasetListItemType>((item) => ({
_id: item._id, _id: item._id,
parentId: item.parentId,
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),
defaultPermission: item.defaultPermission ?? DatasetDefaultPermissionVal defaultPermission: item.defaultPermission ?? DatasetDefaultPermissionVal,
inheritPermission: item.inheritPermission
})) }))
); );

View File

@@ -0,0 +1,45 @@
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import {
ManagePermissionVal,
PerResourceTypeEnum
} from '@fastgpt/global/support/permission/constant';
import { resumeInheritPermission } from '@fastgpt/service/support/permission/inheritPermission';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
export type ResumeInheritPermissionQuery = {
datasetId: string;
};
export type ResumeInheritPermissionBody = {};
// resume the dataset's inherit permission.
async function handler(
req: ApiRequestProps<ResumeInheritPermissionBody, ResumeInheritPermissionQuery>
) {
const { datasetId } = req.query;
const { dataset } = await authDataset({
datasetId,
req,
authToken: true,
per: ManagePermissionVal
});
if (dataset.parentId) {
await resumeInheritPermission({
resource: dataset,
folderTypeList: [DatasetTypeEnum.folder],
resourceType: PerResourceTypeEnum.dataset,
resourceModel: MongoDataset
});
} else {
await MongoDataset.updateOne(
{
_id: datasetId
},
{
inheritPermission: true
}
);
}
}
export default NextAPI(handler);

View File

@@ -1,15 +1,34 @@
import type { NextApiRequest } from 'next';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema'; import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import type { DatasetUpdateBody } from '@fastgpt/global/core/dataset/api.d'; import type { DatasetUpdateBody } from '@fastgpt/global/core/dataset/api.d';
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth'; import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { import {
OwnerPermissionVal, ManagePermissionVal,
PerResourceTypeEnum,
WritePermissionVal WritePermissionVal
} from '@fastgpt/global/support/permission/constant'; } from '@fastgpt/global/support/permission/constant';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common'; import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { ClientSession } from 'mongoose';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
import { DatasetSchemaType } from '@fastgpt/global/core/dataset/type';
import { getResourceAllClbs } from '@fastgpt/service/support/permission/controller';
import {
syncChildrenPermission,
syncCollaborators
} from '@fastgpt/service/support/permission/inheritPermission';
async function handler(req: NextApiRequest) { export type DatasetUpdateQuery = {};
export type DatasetUpdateResponse = any;
async function handler(
req: ApiRequestProps<DatasetUpdateBody, DatasetUpdateQuery>,
_res: ApiResponseType<any>
): Promise<DatasetUpdateResponse> {
const { const {
id, id,
parentId, parentId,
@@ -21,34 +40,131 @@ async function handler(req: NextApiRequest) {
externalReadUrl, externalReadUrl,
defaultPermission, defaultPermission,
status status
} = req.body as DatasetUpdateBody; } = req.body;
if (!id) { if (!id) {
return Promise.reject(CommonErrEnum.missingParams); return Promise.reject(CommonErrEnum.missingParams);
} }
if (defaultPermission) { const { dataset } = (await (async () => {
await authDataset({ req, authToken: true, datasetId: id, per: OwnerPermissionVal }); if (defaultPermission !== undefined) {
} else { return await authDataset({ req, authToken: true, datasetId: id, per: ManagePermissionVal });
await authDataset({ req, authToken: true, datasetId: id, per: WritePermissionVal }); } else {
} return await authDataset({ req, authToken: true, datasetId: id, per: WritePermissionVal });
await MongoDataset.findOneAndUpdate(
{
_id: id
},
{
...(parentId !== undefined && { parentId: parentId || null }),
...(name && { name }),
...(avatar && { avatar }),
...(agentModel && { agentModel: agentModel.model }),
...(websiteConfig && { websiteConfig }),
...(status && { status }),
...(intro && { intro }),
...(externalReadUrl && { externalReadUrl }),
...(defaultPermission !== undefined && { defaultPermission })
} }
); })()) as { dataset: DatasetSchemaType };
}
const isDefaultPermissionChanged =
defaultPermission !== undefined && dataset.defaultPermission !== defaultPermission;
const isFolder = dataset.type === DatasetTypeEnum.folder;
const onUpdate = async (
session?: ClientSession,
updatedDefaultPermission?: PermissionValueType
) => {
await MongoDataset.findByIdAndUpdate(
id,
{
...parseParentIdInMongo(parentId),
...(name && { name }),
...(avatar && { avatar }),
...(agentModel && { agentModel: agentModel.model }),
...(websiteConfig && { websiteConfig }),
...(status && { status }),
...(intro !== undefined && { intro }),
...(externalReadUrl && { externalReadUrl }),
// move
...(updatedDefaultPermission !== undefined && {
defaultPermission: updatedDefaultPermission
}),
// update the defaultPermission
...(isDefaultPermissionChanged && { inheritPermission: false })
},
{ session }
);
};
// move
if (parentId !== undefined) {
await mongoSessionRun(async (session) => {
const parentDefaultPermission = await (async () => {
if (parentId) {
const { dataset: parentDataset } = await authDataset({
req,
authToken: true,
datasetId: parentId,
per: WritePermissionVal
});
return parentDataset.defaultPermission;
}
return DatasetDefaultPermissionVal;
})();
if (isFolder && dataset.inheritPermission) {
const parentClbs = await getResourceAllClbs({
teamId: dataset.teamId,
resourceId: parentId,
resourceType: PerResourceTypeEnum.dataset,
session
});
await syncCollaborators({
teamId: dataset.teamId,
resourceId: id,
resourceType: PerResourceTypeEnum.dataset,
collaborators: parentClbs,
session
});
await syncChildrenPermission({
resource: dataset,
resourceType: PerResourceTypeEnum.dataset,
resourceModel: MongoDataset,
folderTypeList: [DatasetTypeEnum.folder],
collaborators: parentClbs,
defaultPermission: parentDefaultPermission,
session
});
return onUpdate(session, parentDefaultPermission);
}
return onUpdate(session);
});
} else if (isDefaultPermissionChanged) {
await mongoSessionRun(async (session) => {
if (isFolder) {
await syncChildrenPermission({
defaultPermission,
resource: {
_id: dataset._id,
type: dataset.type,
teamId: dataset.teamId,
parentId: dataset.parentId
},
resourceType: PerResourceTypeEnum.dataset,
resourceModel: MongoDataset,
folderTypeList: [DatasetTypeEnum.folder],
session
});
} else if (dataset.inheritPermission && dataset.parentId) {
const parentClbs = await getResourceAllClbs({
teamId: dataset.teamId,
resourceId: parentId,
resourceType: PerResourceTypeEnum.dataset,
session
});
await syncCollaborators({
teamId: dataset.teamId,
resourceId: id,
resourceType: PerResourceTypeEnum.dataset,
collaborators: parentClbs,
session
});
}
return onUpdate(session, defaultPermission);
});
} else {
return onUpdate();
}
}
export default NextAPI(handler); export default NextAPI(handler);

View File

@@ -20,7 +20,6 @@ import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants'
import AIModelSelector from '@/components/Select/AIModelSelector'; import AIModelSelector from '@/components/Select/AIModelSelector';
import { useI18n } from '@/web/context/I18n'; import { useI18n } from '@/web/context/I18n';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useSystem } from '@fastgpt/web/hooks/useSystem';
const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: string }) => { const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: string }) => {
@@ -41,8 +40,7 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
name: '', name: '',
intro: '', intro: '',
vectorModel: filterNotHiddenVectorModelList[0].model, vectorModel: filterNotHiddenVectorModelList[0].model,
agentModel: datasetModelList[0].model, agentModel: datasetModelList[0].model
defaultPermission: DatasetDefaultPermissionVal
} }
}); });
const avatar = watch('avatar'); const avatar = watch('avatar');

View File

@@ -1,5 +1,5 @@
import React, { useMemo, useRef, useState } from 'react'; import React, { useMemo, useRef, useState } from 'react';
import { putDatasetById } from '@/web/core/dataset/api'; import { resumeInheritPer } from '@/web/core/dataset/api';
import { useDatasetStore } from '@/web/core/dataset/store/dataset'; import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import { Box, Flex, Grid } from '@chakra-ui/react'; import { Box, Flex, Grid } from '@chakra-ui/react';
import { DatasetTypeEnum, DatasetTypeMap } from '@fastgpt/global/core/dataset/constants'; import { DatasetTypeEnum, DatasetTypeMap } from '@fastgpt/global/core/dataset/constants';
@@ -42,16 +42,16 @@ function List() {
const { t } = useTranslation(); const { t } = useTranslation();
const { commonT } = useI18n(); const { commonT } = useI18n();
const { const {
refetchDatasets, loadMyDatasets,
setMoveDatasetId, setMoveDatasetId,
refetchPaths, refetchPaths,
refetchFolderDetail,
editedDataset, editedDataset,
setEditedDataset, setEditedDataset,
onDelDataset onDelDataset,
onUpdateDataset,
myDatasets
} = useContextSelector(DatasetsContext, (v) => v); } = useContextSelector(DatasetsContext, (v) => v);
const [editPerDatasetIndex, setEditPerDatasetIndex] = useState<number>(); const [editPerDatasetIndex, setEditPerDatasetIndex] = useState<number>();
const { myDatasets, loadMyDatasets } = useDatasetStore();
const [loadingDatasetId, setLoadingDatasetId] = useState<string>(); const [loadingDatasetId, setLoadingDatasetId] = useState<string>();
const { getBoxProps } = useFolderDrag({ const { getBoxProps } = useFolderDrag({
@@ -61,11 +61,10 @@ function List() {
onDrop: async (dragId: string, targetId: string) => { onDrop: async (dragId: string, targetId: string) => {
setLoadingDatasetId(dragId); setLoadingDatasetId(dragId);
try { try {
await putDatasetById({ await onUpdateDataset({
id: dragId, id: dragId,
parentId: targetId parentId: targetId
}); });
refetchDatasets();
} catch (error) {} } catch (error) {}
setLoadingDatasetId(undefined); setLoadingDatasetId(undefined);
} }
@@ -132,7 +131,7 @@ function List() {
() => () =>
onDelDataset(id).then(() => { onDelDataset(id).then(() => {
refetchPaths(); refetchPaths();
refetchDatasets(); loadMyDatasets();
}), }),
undefined, undefined,
DeleteTipsMap.current[DatasetTypeEnum.dataset] DeleteTipsMap.current[DatasetTypeEnum.dataset]
@@ -350,15 +349,12 @@ function List() {
title={commonT('dataset.Edit Info')} title={commonT('dataset.Edit Info')}
onClose={() => setEditedDataset(undefined)} onClose={() => setEditedDataset(undefined)}
onEdit={async (data) => { onEdit={async (data) => {
await putDatasetById({ await onUpdateDataset({
id: editedDataset.id, id: editedDataset.id,
name: data.name, name: data.name,
intro: data.intro, intro: data.intro,
avatar: data.avatar avatar: data.avatar
}); });
loadMyDatasets(parentId ? parentId : undefined);
refetchFolderDetail();
refetchPaths();
setEditedDataset(undefined); setEditedDataset(undefined);
}} }}
/> />
@@ -366,18 +362,22 @@ function List() {
{!!editPerDataset && ( {!!editPerDataset && (
<ConfigPerModal <ConfigPerModal
hasParent={!!parentId}
refetchResource={loadMyDatasets}
isInheritPermission={editPerDataset.inheritPermission}
resumeInheritPermission={() =>
resumeInheritPer(editPerDataset._id).then(() => Promise.all([loadMyDatasets()]))
}
avatar={editPerDataset.avatar} avatar={editPerDataset.avatar}
name={editPerDataset.name} name={editPerDataset.name}
defaultPer={{ defaultPer={{
value: editPerDataset.defaultPermission, value: editPerDataset.defaultPermission,
defaultValue: DatasetDefaultPermissionVal, defaultValue: DatasetDefaultPermissionVal,
onChange: async (e) => { onChange: (e) =>
await putDatasetById({ onUpdateDataset({
id: editPerDataset._id, id: editPerDataset._id,
defaultPermission: e defaultPermission: e
}); })
refetchDatasets();
}
}} }}
managePer={{ managePer={{
permission: editPerDataset.permission, permission: editPerDataset.permission,
@@ -400,7 +400,8 @@ function List() {
deleteDatasetCollaborators({ deleteDatasetCollaborators({
datasetId: editPerDataset._id, datasetId: editPerDataset._id,
tmbId tmbId
}) }),
refreshDeps: [editPerDataset._id, editPerDataset.inheritPermission]
}} }}
onClose={() => setEditPerDatasetIndex(undefined)} onClose={() => setEditPerDatasetIndex(undefined)}
/> />

View File

@@ -5,7 +5,6 @@ import {
getDatasetById, getDatasetById,
delDatasetById delDatasetById
} from '@/web/core/dataset/api'; } from '@/web/core/dataset/api';
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import { import {
GetResourceFolderListProps, GetResourceFolderListProps,
ParentIdType, ParentIdType,
@@ -19,16 +18,17 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { DatasetUpdateBody } from '@fastgpt/global/core/dataset/api'; import { DatasetUpdateBody } from '@fastgpt/global/core/dataset/api';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { DatasetItemType } from '@fastgpt/global/core/dataset/type'; import { DatasetItemType, DatasetListItemType } from '@fastgpt/global/core/dataset/type';
import { EditResourceInfoFormType } from '@/components/common/Modal/EditResourceModal'; import { EditResourceInfoFormType } from '@/components/common/Modal/EditResourceModal';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
const MoveModal = dynamic(() => import('@/components/common/folder/MoveModal')); const MoveModal = dynamic(() => import('@/components/common/folder/MoveModal'));
export type DatasetContextType = { export type DatasetContextType = {
refetchDatasets: () => void; myDatasets: DatasetListItemType[];
loadMyDatasets: () => Promise<DatasetListItemType[]>;
refetchPaths: () => void; refetchPaths: () => void;
refetchFolderDetail: () => void; refetchFolderDetail: () => Promise<DatasetItemType | undefined>;
isFetchingDatasets: boolean; isFetchingDatasets: boolean;
setMoveDatasetId: (id: string) => void; setMoveDatasetId: (id: string) => void;
paths: ParentTreePathItemType[]; paths: ParentTreePathItemType[];
@@ -36,28 +36,48 @@ export type DatasetContextType = {
editedDataset?: EditResourceInfoFormType; editedDataset?: EditResourceInfoFormType;
setEditedDataset: (data?: EditResourceInfoFormType) => void; setEditedDataset: (data?: EditResourceInfoFormType) => void;
onDelDataset: (id: string) => Promise<void>; onDelDataset: (id: string) => Promise<void>;
onUpdateDataset: (data: DatasetUpdateBody) => Promise<void>;
}; };
export const DatasetsContext = createContext<DatasetContextType>({ export const DatasetsContext = createContext<DatasetContextType>({
refetchDatasets: () => {},
isFetchingDatasets: false, isFetchingDatasets: false,
setMoveDatasetId: () => {}, setMoveDatasetId: () => {},
refetchPaths: () => {}, refetchPaths: () => {},
paths: [], paths: [],
refetchFolderDetail: () => {},
folderDetail: {} as any, folderDetail: {} as any,
editedDataset: {} as any, editedDataset: {} as any,
setEditedDataset: () => {}, setEditedDataset: () => {},
onDelDataset: () => Promise.resolve() onDelDataset: () => Promise.resolve(),
loadMyDatasets: function (): Promise<DatasetListItemType[]> {
throw new Error('Function not implemented.');
},
refetchFolderDetail: function (): Promise<DatasetItemType | undefined> {
throw new Error('Function not implemented.');
},
onUpdateDataset: function (_data: DatasetUpdateBody): Promise<void> {
throw new Error('Function not implemented.');
},
myDatasets: []
}); });
function DatasetContextProvider({ children }: { children: React.ReactNode }) { function DatasetContextProvider({ children }: { children: React.ReactNode }) {
const router = useRouter(); const router = useRouter();
const { commonT } = useI18n(); const { commonT } = useI18n();
const { t } = useTranslation(); const { t } = useTranslation();
const [moveDatasetId, setMoveDatasetId] = useState<string>();
const { parentId = null } = router.query as { parentId?: string | null }; const { parentId = null } = router.query as { parentId?: string | null };
const { myDatasets, loadMyDatasets } = useDatasetStore();
const { data: myDatasets = [], runAsync: loadMyDatasets } = useRequest2(
() =>
getDatasets({
parentId
}),
{
manual: false,
refreshDeps: [parentId]
}
);
const { data: folderDetail, runAsync: refetchFolderDetail } = useRequest2( const { data: folderDetail, runAsync: refetchFolderDetail } = useRequest2(
() => (parentId ? getDatasetById(parentId) : Promise.resolve(undefined)), () => (parentId ? getDatasetById(parentId) : Promise.resolve(undefined)),
@@ -66,17 +86,6 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
refreshDeps: [parentId, myDatasets] refreshDeps: [parentId, myDatasets]
} }
); );
const getDatasetFolderList = useCallback(({ parentId }: GetResourceFolderListProps) => {
return getDatasets({
parentId,
type: DatasetTypeEnum.folder
}).then((res) => {
return res.map((item) => ({
id: item._id,
name: item.name
}));
});
}, []);
const { data: paths = [], runAsync: refetchPaths } = useRequest2( const { data: paths = [], runAsync: refetchPaths } = useRequest2(
() => getDatasetPaths(parentId), () => getDatasetPaths(parentId),
@@ -87,21 +96,16 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
); );
const { runAsync: refetchDatasets, loading: isFetchingDatasets } = useRequest2( const { runAsync: refetchDatasets, loading: isFetchingDatasets } = useRequest2(
() => loadMyDatasets(parentId ?? undefined), () => loadMyDatasets(),
{ {
manual: false, manual: false,
refreshDeps: [parentId] refreshDeps: [parentId]
} }
); );
const [moveDatasetId, setMoveDatasetId] = useState<string>(); const { runAsync: onUpdateDataset } = useRequest2(putDatasetById, {
onSuccess: () => Promise.all([refetchDatasets(), refetchPaths(), loadMyDatasets()])
const { runAsync: onUpdateDataset } = useRequest2((data: DatasetUpdateBody) => });
putDatasetById(data).then(async (res) => {
await Promise.all([refetchDatasets(), refetchPaths()]);
return res;
})
);
const onMoveDataset = useCallback( const onMoveDataset = useCallback(
async (parentId: ParentIdType) => { async (parentId: ParentIdType) => {
@@ -114,6 +118,18 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
[moveDatasetId, onUpdateDataset] [moveDatasetId, onUpdateDataset]
); );
const getDatasetFolderList = useCallback(async ({ parentId }: GetResourceFolderListProps) => {
return (
await getDatasets({
parentId,
type: DatasetTypeEnum.folder
})
).map((item) => ({
id: item._id,
name: item.name
}));
}, []);
const [editedDataset, setEditedDataset] = useState<EditResourceInfoFormType>(); const [editedDataset, setEditedDataset] = useState<EditResourceInfoFormType>();
const { runAsync: onDelDataset } = useRequest2(delDatasetById, { const { runAsync: onDelDataset } = useRequest2(delDatasetById, {
@@ -131,7 +147,10 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
folderDetail, folderDetail,
editedDataset, editedDataset,
setEditedDataset, setEditedDataset,
onDelDataset onDelDataset,
onUpdateDataset,
myDatasets,
loadMyDatasets
}; };
return ( return (

View File

@@ -5,7 +5,6 @@ import PageContainer from '@/components/PageContainer';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { serviceSideProps } from '@/web/common/utils/i18n'; import { serviceSideProps } from '@/web/common/utils/i18n';
import ParentPaths from '@/components/common/folder/Path'; import ParentPaths from '@/components/common/folder/Path';
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import List from './component/List'; import List from './component/List';
import { DatasetsContext } from './context'; import { DatasetsContext } from './context';
import DatasetContextProvider from './context'; import DatasetContextProvider from './context';
@@ -14,13 +13,11 @@ import MyMenu from '@fastgpt/web/components/common/MyMenu';
import { AddIcon } from '@chakra-ui/icons'; import { AddIcon } from '@chakra-ui/icons';
import { useUserStore } from '@/web/support/user/useUserStore'; import { useUserStore } from '@/web/support/user/useUserStore';
import MyIcon from '@fastgpt/web/components/common/Icon'; import MyIcon from '@fastgpt/web/components/common/Icon';
import { FolderIcon, FolderImgUrl } from '@fastgpt/global/common/file/image/constants'; import { FolderIcon } from '@fastgpt/global/common/file/image/constants';
import { EditFolderFormType } from '@fastgpt/web/components/common/MyModal/EditFolderModal'; import { EditFolderFormType } from '@fastgpt/web/components/common/MyModal/EditFolderModal';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { postCreateDataset, putDatasetById } from '@/web/core/dataset/api'; import { postCreateDatasetFolder, resumeInheritPer } from '@/web/core/dataset/api';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import FolderSlideCard from '@/components/common/folder/SlideCard'; import FolderSlideCard from '@/components/common/folder/SlideCard';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { import {
DatasetDefaultPermissionVal, DatasetDefaultPermissionVal,
DatasetPermissionList DatasetPermissionList
@@ -44,17 +41,18 @@ const Dataset = () => {
const router = useRouter(); const router = useRouter();
const { parentId } = router.query as { parentId: string }; const { parentId } = router.query as { parentId: string };
const { myDatasets } = useDatasetStore();
const { const {
myDatasets,
paths, paths,
isFetchingDatasets, isFetchingDatasets,
refetchPaths, refetchPaths,
refetchDatasets, loadMyDatasets,
refetchFolderDetail,
folderDetail, folderDetail,
setEditedDataset, setEditedDataset,
setMoveDatasetId, setMoveDatasetId,
onDelDataset onDelDataset,
onUpdateDataset
} = useContextSelector(DatasetsContext, (v) => v); } = useContextSelector(DatasetsContext, (v) => v);
const { userInfo } = useUserStore(); const { userInfo } = useUserStore();
@@ -139,7 +137,11 @@ const Dataset = () => {
{!!folderDetail && isPc && ( {!!folderDetail && isPc && (
<Box ml="6"> <Box ml="6">
<FolderSlideCard <FolderSlideCard
refreshDeps={[folderDetail._id]} resumeInheritPermission={() => resumeInheritPer(folderDetail._id)}
isInheritPermission={folderDetail.inheritPermission}
hasParent={!!folderDetail.parentId}
refetchResource={() => Promise.all([refetchFolderDetail(), loadMyDatasets()])}
refreshDeps={[folderDetail._id, folderDetail.inheritPermission]}
name={folderDetail.name} name={folderDetail.name}
intro={folderDetail.intro} intro={folderDetail.intro}
onEdit={() => { onEdit={() => {
@@ -165,7 +167,7 @@ const Dataset = () => {
value: folderDetail.defaultPermission, value: folderDetail.defaultPermission,
defaultValue: DatasetDefaultPermissionVal, defaultValue: DatasetDefaultPermissionVal,
onChange: (e) => { onChange: (e) => {
return putDatasetById({ return onUpdateDataset({
id: folderDetail._id, id: folderDetail._id,
defaultPermission: e defaultPermission: e
}); });
@@ -192,7 +194,8 @@ const Dataset = () => {
deleteDatasetCollaborators({ deleteDatasetCollaborators({
datasetId: folderDetail._id, datasetId: folderDetail._id,
tmbId tmbId
}) }),
refreshDeps: [folderDetail._id, folderDetail.inheritPermission]
}} }}
/> />
</Box> </Box>
@@ -202,16 +205,14 @@ const Dataset = () => {
{!!editFolderData && ( {!!editFolderData && (
<EditFolderModal <EditFolderModal
onClose={() => setEditFolderData(undefined)} onClose={() => setEditFolderData(undefined)}
onCreate={async ({ name }) => { onCreate={async ({ name, intro }) => {
try { try {
await postCreateDataset({ await postCreateDatasetFolder({
parentId: parentId || undefined, parentId: parentId || undefined,
name, name,
type: DatasetTypeEnum.folder, intro: intro ?? ''
avatar: FolderImgUrl,
intro: ''
}); });
refetchDatasets(); loadMyDatasets();
refetchPaths(); refetchPaths();
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
@@ -219,13 +220,11 @@ const Dataset = () => {
}} }}
onEdit={async ({ name, intro, id }) => { onEdit={async ({ name, intro, id }) => {
try { try {
await putDatasetById({ await onUpdateDataset({
id, id,
name, name,
intro intro
}); });
refetchDatasets();
refetchPaths();
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }

View File

@@ -42,6 +42,7 @@ import type { GetDatasetListBody } from '@/pages/api/core/dataset/list';
import type { UpdateDatasetCollectionParams } from '@/pages/api/core/dataset/collection/update'; import type { UpdateDatasetCollectionParams } from '@/pages/api/core/dataset/collection/update';
import type { GetDatasetDataListProps } from '@/pages/api/core/dataset/data/list'; import type { GetDatasetDataListProps } from '@/pages/api/core/dataset/data/list';
import type { UpdateDatasetDataProps } from '@fastgpt/global/core/dataset/controller'; import type { UpdateDatasetDataProps } from '@fastgpt/global/core/dataset/controller';
import type { DatasetFolderCreateBody } from '@/pages/api/core/dataset/folder/create';
/* ======================== dataset ======================= */ /* ======================== dataset ======================= */
export const getDatasets = (data: GetDatasetListBody) => export const getDatasets = (data: GetDatasetListBody) =>
@@ -69,6 +70,12 @@ export const postWebsiteSync = (data: PostWebsiteSyncParams) =>
timeout: 600000 timeout: 600000
}).catch(); }).catch();
export const postCreateDatasetFolder = (data: DatasetFolderCreateBody) =>
POST(`/core/dataset/folder/create`, data);
export const resumeInheritPer = (datasetId: string) =>
GET(`/core/dataset/resumeInheritPermission`, { datasetId });
/* =========== search test ============ */ /* =========== search test ============ */
export const postSearchText = (data: SearchTestProps) => export const postSearchText = (data: SearchTestProps) =>
POST<SearchTestResponse>(`/core/dataset/searchTest`, data); POST<SearchTestResponse>(`/core/dataset/searchTest`, data);

View File

@@ -26,7 +26,8 @@ export const defaultDatasetDetail: DatasetItemType = {
permission: new DatasetPermission(), permission: new DatasetPermission(),
vectorModel: defaultVectorModels[0], vectorModel: defaultVectorModels[0],
agentModel: defaultQAModels[0], agentModel: defaultQAModels[0],
defaultPermission: DatasetDefaultPermissionVal defaultPermission: DatasetDefaultPermissionVal,
inheritPermission: true
}; };
export const defaultCollectionDetail: DatasetCollectionItemType = { export const defaultCollectionDetail: DatasetCollectionItemType = {
@@ -47,7 +48,8 @@ export const defaultCollectionDetail: DatasetCollectionItemType = {
status: 'active', status: 'active',
vectorModel: defaultVectorModels[0].model, vectorModel: defaultVectorModels[0].model,
agentModel: defaultQAModels[0].model, agentModel: defaultQAModels[0].model,
defaultPermission: DatasetDefaultPermissionVal defaultPermission: DatasetDefaultPermissionVal,
inheritPermission: true
}, },
parentId: '', parentId: '',
name: '', name: '',

View File

@@ -11,7 +11,7 @@ type State = {
allDatasets: DatasetSimpleItemType[]; allDatasets: DatasetSimpleItemType[];
loadAllDatasets: () => Promise<DatasetSimpleItemType[]>; loadAllDatasets: () => Promise<DatasetSimpleItemType[]>;
myDatasets: DatasetListItemType[]; myDatasets: DatasetListItemType[];
loadMyDatasets: (parentId?: string) => Promise<any>; loadMyDatasets: (parentId?: string) => Promise<DatasetListItemType[]>;
}; };
export const useDatasetStore = create<State>()( export const useDatasetStore = create<State>()(