feat: team permission refine (#4494) (#4498)

* feat: team permission refine (#4402)

* chore: team permission extend

* feat: manage team permission

* chore: api auth

* fix: i18n

* feat: add initv493

* fix: test, org auth manager

* test: app test for refined permission

* update init sh

* fix: add/remove manage permission (#4427)

* fix: add/remove manage permission

* fix: github action fastgpt-test

* fix: mock create model

* fix: team write permission

* fix: ts

* account permission

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
This commit is contained in:
Archer
2025-04-10 11:11:54 +08:00
committed by GitHub
parent 80f41dd2a9
commit 199f454b6b
51 changed files with 1116 additions and 460 deletions

View File

@@ -4,6 +4,7 @@ import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { onCreateApp } from './create';
import { TeamAppCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
export type copyAppQuery = {};
@@ -17,19 +18,16 @@ async function handler(
req: ApiRequestProps<copyAppBody, copyAppQuery>,
res: ApiResponseType<any>
): Promise<copyAppResponse> {
const [{ app, tmbId }] = await Promise.all([
authApp({
req,
authToken: true,
per: WritePermissionVal,
appId: req.body.appId
}),
authUserPer({
req,
authToken: true,
per: WritePermissionVal
})
]);
const { app } = await authApp({
req,
authToken: true,
per: WritePermissionVal,
appId: req.body.appId
});
const { tmbId } = app.parentId
? await authApp({ req, appId: app.parentId, per: TeamAppCreatePermissionVal, authToken: true })
: await authUserPer({ req, authToken: true, per: TeamAppCreatePermissionVal });
const appId = await onCreateApp({
parentId: app.parentId,

View File

@@ -17,6 +17,7 @@ import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
import { TeamAppCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
export type CreateAppBody = {
parentId?: ParentIdType;
@@ -36,18 +37,15 @@ async function handler(req: ApiRequestProps<CreateAppBody>) {
}
// 凭证校验
const [{ teamId, tmbId, userId }] = await Promise.all([
authUserPer({ req, authToken: true, per: WritePermissionVal }),
...(parentId
? [authApp({ req, appId: parentId, per: WritePermissionVal, authToken: true })]
: [])
]);
const { teamId, tmbId, userId } = parentId
? await authApp({ req, appId: parentId, per: TeamAppCreatePermissionVal, authToken: true })
: await authUserPer({ req, authToken: true, per: TeamAppCreatePermissionVal });
// 上限校验
await checkTeamAppLimit(teamId);
const tmb = await MongoTeamMember.findById({ _id: tmbId }, 'userId').populate<{
user: { avatar: string; username: string };
}>('user', 'avatar username');
user: { username: string };
}>('user', 'username');
// 创建app
const appId = await onCreateApp({
@@ -60,7 +58,7 @@ async function handler(req: ApiRequestProps<CreateAppBody>) {
chatConfig,
teamId,
tmbId,
userAvatar: tmb?.user?.avatar,
userAvatar: tmb?.avatar,
username: tmb?.user?.username
});

View File

@@ -16,7 +16,7 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { syncCollaborators } from '@fastgpt/service/support/permission/inheritPermission';
import { getResourceClbsAndGroups } from '@fastgpt/service/support/permission/controller';
import { TeamWritePermissionVal } from '@fastgpt/global/support/permission/user/constant';
import { TeamAppCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
export type CreateAppFolderBody = {
@@ -33,21 +33,9 @@ async function handler(req: ApiRequestProps<CreateAppFolderBody>) {
}
// 凭证校验
const { teamId, tmbId } = await authUserPer({
req,
authToken: true,
per: TeamWritePermissionVal
});
if (parentId) {
// if it is not a root folder
await authApp({
req,
appId: parentId,
per: WritePermissionVal,
authToken: true
});
}
const { teamId, tmbId } = parentId
? await authApp({ req, appId: parentId, per: TeamAppCreatePermissionVal, authToken: true })
: await authUserPer({ req, authToken: true, per: TeamAppCreatePermissionVal });
// Create app
await mongoSessionRun(async (session) => {

View File

@@ -9,6 +9,8 @@ import { onCreateApp, type CreateAppBody } from '../create';
import { AppSchema } from '@fastgpt/global/core/app/type';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { TeamAppCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
export type createHttpPluginQuery = {};
@@ -29,11 +31,9 @@ async function handler(
return Promise.reject('缺少参数');
}
const { teamId, tmbId, userId } = await authUserPer({
req,
authToken: true,
per: WritePermissionVal
});
const { teamId, tmbId, userId } = parentId
? await authApp({ req, appId: parentId, per: TeamAppCreatePermissionVal, authToken: true })
: await authUserPer({ req, authToken: true, per: TeamAppCreatePermissionVal });
await mongoSessionRun(async (session) => {
// create http plugin folder

View File

@@ -20,7 +20,7 @@ import { ClientSession } from 'mongoose';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { getResourceClbsAndGroups } from '@fastgpt/service/support/permission/controller';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { TeamWritePermissionVal } from '@fastgpt/global/support/permission/user/constant';
import { TeamAppCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
@@ -79,7 +79,7 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
await authUserPer({
req,
authToken: true,
per: TeamWritePermissionVal
per: TeamAppCreatePermissionVal
});
}
} else {

View File

@@ -6,11 +6,9 @@ import {
getLLMModel,
getEmbeddingModel,
getDatasetModel,
getDefaultEmbeddingModel,
getVlmModel
getDefaultEmbeddingModel
} from '@fastgpt/service/core/ai/model';
import { checkTeamDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { NextAPI } from '@/service/middleware/entry';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
@@ -18,6 +16,7 @@ import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
import { TeamDatasetCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
export type DatasetCreateQuery = {};
export type DatasetCreateBody = CreateDatasetParams;
@@ -41,25 +40,20 @@ async function handler(
} = req.body;
// auth
const [{ teamId, tmbId, userId }] = await Promise.all([
authUserPer({
req,
authToken: true,
authApiKey: true,
per: WritePermissionVal
}),
...(parentId
? [
authDataset({
req,
datasetId: parentId,
authToken: true,
authApiKey: true,
per: WritePermissionVal
})
]
: [])
]);
const { teamId, tmbId, userId } = parentId
? await authDataset({
req,
datasetId: parentId,
authToken: true,
authApiKey: true,
per: TeamDatasetCreatePermissionVal
})
: await authUserPer({
req,
authToken: true,
authApiKey: true,
per: TeamDatasetCreatePermissionVal
});
// check model valid
const vectorModelStore = getEmbeddingModel(vectorModel);

View File

@@ -5,8 +5,7 @@ import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import {
OwnerPermissionVal,
PerResourceTypeEnum,
WritePermissionVal
PerResourceTypeEnum
} from '@fastgpt/global/support/permission/constant';
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
@@ -16,6 +15,7 @@ import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { getResourceClbsAndGroups } from '@fastgpt/service/support/permission/controller';
import { syncCollaborators } from '@fastgpt/service/support/permission/inheritPermission';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
import { TeamDatasetCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
export type DatasetFolderCreateQuery = {};
export type DatasetFolderCreateBody = {
parentId?: string;
@@ -33,20 +33,20 @@ async function handler(
return Promise.reject(CommonErrEnum.missingParams);
}
const { tmbId, teamId } = await authUserPer({
req,
per: WritePermissionVal,
authToken: true
});
if (parentId) {
await authDataset({
datasetId: parentId,
per: WritePermissionVal,
req,
authToken: true
});
}
const { teamId, tmbId } = parentId
? await authDataset({
req,
datasetId: parentId,
authToken: true,
authApiKey: true,
per: TeamDatasetCreatePermissionVal
})
: await authUserPer({
req,
authToken: true,
authApiKey: true,
per: TeamDatasetCreatePermissionVal
});
await mongoSessionRun(async (session) => {
const dataset = await MongoDataset.create({

View File

@@ -23,7 +23,7 @@ import {
syncCollaborators
} from '@fastgpt/service/support/permission/inheritPermission';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { TeamWritePermissionVal } from '@fastgpt/global/support/permission/user/constant';
import { TeamDatasetCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema';
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
@@ -104,7 +104,7 @@ async function handler(
await authUserPer({
req,
authToken: true,
per: TeamWritePermissionVal
per: TeamDatasetCreatePermissionVal
});
}
} else {

View File

@@ -4,12 +4,10 @@ import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { getNanoid } from '@fastgpt/global/common/string/tools';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import {
ManagePermissionVal,
WritePermissionVal
} from '@fastgpt/global/support/permission/constant';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { OpenApiErrEnum } from '@fastgpt/global/common/error/code/openapi';
import { TeamApikeyCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
async function handler(req: ApiRequestProps<EditApiKeyProps>): Promise<string> {
const { appId, name, limit } = req.body;
@@ -19,7 +17,7 @@ async function handler(req: ApiRequestProps<EditApiKeyProps>): Promise<string> {
const { teamId, tmbId } = await authUserPer({
req,
authToken: true,
per: WritePermissionVal
per: TeamApikeyCreatePermissionVal
});
return { teamId, tmbId };
} else {

View File

@@ -31,6 +31,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
import TemplateMarketModal from '@/pageComponents/app/list/TemplateMarketModal';
import MyImage from '@fastgpt/web/components/common/Image/MyImage';
import JsonImportModal from '@/pageComponents/app/list/JsonImportModal';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
const CreateModal = dynamic(() => import('@/pageComponents/app/list/CreateModal'));
const EditFolderModal = dynamic(
@@ -213,7 +214,7 @@ const MyApps = () => {
{(folderDetail
? folderDetail.permission.hasWritePer && folderDetail?.type !== AppTypeEnum.httpPlugin
: userInfo?.team.permission.hasWritePer) && (
: userInfo?.team.permission.hasAppCreatePer) && (
<MyMenu
size="md"
Button={
@@ -327,7 +328,7 @@ const MyApps = () => {
}: {
members?: string[];
groups?: string[];
permission: number;
permission: PermissionValueType;
}) => {
return postUpdateAppCollaborators({
members,

View File

@@ -29,6 +29,7 @@ import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { useToast } from '@fastgpt/web/hooks/useToast';
import MyBox from '@fastgpt/web/components/common/MyBox';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
const EditFolderModal = dynamic(
() => import('@fastgpt/web/components/common/MyModal/EditFolderModal')
@@ -138,7 +139,7 @@ const Dataset = () => {
{(folderDetail
? folderDetail.permission.hasWritePer
: userInfo?.team?.permission.hasWritePer) && (
: userInfo?.team?.permission.hasDatasetCreatePer) && (
<Box pl={[0, 4]}>
<MyMenu
size="md"
@@ -248,7 +249,7 @@ const Dataset = () => {
}: {
members?: string[];
groups?: string[];
permission: number;
permission: PermissionValueType;
}) =>
postUpdateDatasetCollaborators({
members,