Permission (#1687)

Co-authored-by: Archer <545436317@qq.com>
Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
This commit is contained in:
Archer
2024-06-04 17:52:00 +08:00
committed by GitHub
parent fcb915c988
commit 19c8a06d51
109 changed files with 2291 additions and 1091 deletions

View File

@@ -265,7 +265,7 @@ const MyInfo = () => {
<Box flex={1}>
<strong>{formatStorePrice2Read(userInfo?.team?.balance).toFixed(3)}</strong>
</Box>
{feConfigs?.show_pay && userInfo?.team?.canWrite && (
{feConfigs?.show_pay && userInfo?.team?.permission.hasWritePer && (
<Button variant={'whitePrimary'} size={'sm'} ml={5} onClick={onOpenPayModal}>
{t('user.Pay')}
</Button>

View File

@@ -105,7 +105,7 @@ const UsageTable = () => {
px={[3, 8]}
alignItems={['flex-end', 'center']}
>
{tmbList.length > 1 && userInfo?.team?.canWrite && (
{tmbList.length > 1 && userInfo?.team?.permission.hasWritePer && (
<Flex alignItems={'center'}>
<Box mr={2} flexShrink={0}>
{t('support.user.team.member')}

View File

@@ -51,7 +51,7 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
}
]
: []),
...(feConfigs?.show_pay && userInfo?.team.canWrite
...(feConfigs?.show_pay && userInfo?.team?.permission.hasWritePer
? [
{
icon: 'support/bill/payRecordLight',
@@ -70,7 +70,7 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
}
]
: []),
...(userInfo?.team.canWrite
...(userInfo?.team?.permission.hasWritePer
? [
{
icon: 'support/outlink/apikeyLight',

View File

@@ -3,11 +3,12 @@ import { jsonRes } from '@fastgpt/service/common/response';
import type { CreateAppParams } from '@/global/core/app/api.d';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { checkTeamAppLimit } from '@fastgpt/service/support/permission/teamLimit';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const {
@@ -23,7 +24,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
}
// 凭证校验
const { teamId, tmbId } = await authUserNotVisitor({ req, authToken: true });
const { teamId, tmbId } = await authUserPer({ req, authToken: true, per: WritePermissionVal });
// 上限校验
await checkTeamAppLimit(teamId);

View File

@@ -2,12 +2,13 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { NextAPI } from '@/service/middleware/entry';
import { MongoChatInputGuide } from '@fastgpt/service/core/chat/inputGuide/schema';
import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string };
@@ -17,7 +18,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
}
// 凭证校验
await authApp({ req, authToken: true, appId, per: 'owner' });
await authApp({ req, authToken: true, appId, per: OwnerPermissionVal });
// 删除对应的聊天
await mongoSessionRun(async (session) => {

View File

@@ -1,6 +1,7 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
/* 获取我的模型 */
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
@@ -9,9 +10,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
if (!appId) {
throw new Error('参数错误');
}
// 凭证校验
const { app } = await authApp({ req, authToken: true, appId, per: 'w' });
const { app } = await authApp({ req, authToken: true, appId, per: WritePermissionVal });
return app;
}

View File

@@ -5,9 +5,10 @@ import { AppLogsListItemType } from '@/types/app';
import { Types } from '@fastgpt/service/common/mongo';
import { addDays } from 'date-fns';
import type { GetAppChatLogsParams } from '@/global/core/api/appReq.d';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { ChatItemCollectionName } from '@fastgpt/service/core/chat/chatItemSchema';
import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
async function handler(
req: NextApiRequest,
@@ -26,7 +27,7 @@ async function handler(
}
// 凭证校验
const { teamId } = await authApp({ req, authToken: true, appId, per: 'w' });
const { teamId } = await authApp({ req, authToken: true, appId, per: WritePermissionVal });
const where = {
teamId: new Types.ObjectId(teamId),

View File

@@ -1,29 +1,63 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { mongoRPermission } from '@fastgpt/global/support/permission/utils';
import { AppListItemType } from '@fastgpt/global/core/app/type';
import { authUserRole } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { NextAPI } from '@/service/middleware/entry';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
import {
PerResourceTypeEnum,
ReadPermissionVal
} from '@fastgpt/global/support/permission/constant';
import { AppPermission } from '@fastgpt/global/support/permission/app/controller';
async function handler(req: NextApiRequest, res: NextApiResponse<any>): Promise<AppListItemType[]> {
// 凭证校验
const { teamId, tmbId, teamOwner, role } = await authUserRole({ req, authToken: true });
// 根据 userId 获取模型信息
const myApps = await MongoApp.find(
{ ...mongoRPermission({ teamId, tmbId, role }) },
'_id avatar name intro tmbId permission'
).sort({
updateTime: -1
const {
teamId,
tmbId,
permission: tmbPer
} = await authUserPer({
req,
authToken: true,
per: ReadPermissionVal
});
return myApps.map((app) => ({
/* temp: get all apps and per */
const [myApps, rpList] = await Promise.all([
MongoApp.find({ teamId }, '_id avatar name intro tmbId defaultPermission')
.sort({
updateTime: -1
})
.lean(),
MongoResourcePermission.find({
resourceType: PerResourceTypeEnum.app,
teamId,
tmbId
}).lean()
]);
const filterApps = myApps
.map((app) => {
const perVal = rpList.find((item) => String(item.resourceId) === String(app._id))?.permission;
const Per = new AppPermission({
per: perVal ?? app.defaultPermission,
isOwner: String(app.tmbId) === tmbId || tmbPer.isOwner
});
return {
...app,
permission: Per
};
})
.filter((app) => app.permission.hasReadPer);
return filterApps.map((app) => ({
_id: app._id,
avatar: app.avatar,
name: app.name,
intro: app.intro,
isOwner: teamOwner || String(app.tmbId) === tmbId,
permission: app.permission
permission: app.permission,
defaultPermission: app.defaultPermission
}));
}

View File

@@ -1,14 +1,29 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import type { AppUpdateParams } from '@/global/core/app/api';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { beforeUpdateAppFormat } from '@fastgpt/service/core/app/controller';
import { NextAPI } from '@/service/middleware/entry';
import {
ManagePermissionVal,
WritePermissionVal,
OwnerPermissionVal
} from '@fastgpt/global/support/permission/constant';
/* 获取我的模型 */
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { name, avatar, type, intro, nodes, edges, chatConfig, permission, teamTags } =
req.body as AppUpdateParams;
const {
name,
avatar,
type,
intro,
nodes,
edges,
chatConfig,
permission,
teamTags,
defaultPermission
} = req.body as AppUpdateParams;
const { appId } = req.query as { appId: string };
if (!appId) {
@@ -16,7 +31,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
}
// 凭证校验
await authApp({ req, authToken: true, appId, per: permission ? 'owner' : 'w' });
if (permission) {
await authApp({ req, authToken: true, appId, per: OwnerPermissionVal });
} else if (defaultPermission) {
await authApp({ req, authToken: true, appId, per: ManagePermissionVal });
} else {
await authApp({ req, authToken: true, appId, per: WritePermissionVal });
}
// format nodes data
// 1. dataset search limit, less than model quoteMaxToken
@@ -33,6 +54,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
avatar,
intro,
permission,
defaultPermission,
...(teamTags && teamTags),
...(formatNodes && {
modules: formatNodes

View File

@@ -1,12 +1,13 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { NextAPI } from '@/service/middleware/entry';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { beforeUpdateAppFormat } from '@fastgpt/service/core/app/controller';
import { getNextTimeByCronStringAndTimezone } from '@fastgpt/global/common/string/time';
import { PostPublishAppProps } from '@/global/core/app/api';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
type Response = {};
@@ -14,7 +15,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>): Promise<
const { appId } = req.query as { appId: string };
const { nodes = [], edges = [], chatConfig, type } = req.body as PostPublishAppProps;
await authApp({ appId, req, per: 'w', authToken: true });
await authApp({ appId, req, per: WritePermissionVal, authToken: true });
const { nodes: formatNodes } = beforeUpdateAppFormat({ nodes });

View File

@@ -1,12 +1,13 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { NextAPI } from '@/service/middleware/entry';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { beforeUpdateAppFormat } from '@fastgpt/service/core/app/controller';
import { getNextTimeByCronStringAndTimezone } from '@fastgpt/global/common/string/time';
import { PostRevertAppProps } from '@/global/core/app/api';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
type Response = {};
@@ -14,7 +15,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>): Promise<
const { appId } = req.query as { appId: string };
const { editNodes = [], editEdges = [], versionId } = req.body as PostRevertAppProps;
await authApp({ appId, req, per: 'w', authToken: true });
await authApp({ appId, req, per: WritePermissionVal, authToken: true });
const version = await MongoAppVersion.findOne({
_id: versionId,

View File

@@ -10,7 +10,7 @@ import type {
ChatItemValueItemType,
UserChatItemValueItemType
} from '@fastgpt/global/core/chat/type';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
@@ -18,6 +18,7 @@ import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/type/edge';
import { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type';
import { removeEmptyUserInput } from '@fastgpt/global/core/chat/utils';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
export type Props = {
history: ChatItemType[];
@@ -61,7 +62,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
/* user auth */
const [_, { teamId, tmbId }] = await Promise.all([
authApp({ req, authToken: true, appId, per: 'r' }),
authApp({ req, authToken: true, appId, per: ReadPermissionVal }),
authCert({
req,
authToken: true

View File

@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { getGuideModule, getAppChatConfig } from '@fastgpt/global/core/workflow/utils';
import { getChatModelNameListByModules } from '@/service/core/app/workflow';
import type { InitChatProps, InitChatResponse } from '@/global/core/chat/api.d';
@@ -10,6 +10,7 @@ import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
async function handler(
req: NextApiRequest,
@@ -30,13 +31,13 @@ async function handler(
req,
authToken: true,
appId,
per: 'r'
per: ReadPermissionVal
}),
chatId ? MongoChat.findOne({ appId, chatId }) : undefined
]);
// auth chat permission
if (chat && !app.canWrite && String(tmbId) !== String(chat?.tmbId)) {
if (chat && !app.permission.hasManagePer && String(tmbId) !== String(chat?.tmbId)) {
throw new Error(ChatErrEnum.unAuthChat);
}

View File

@@ -1,7 +1,8 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { MongoChatInputGuide } from '@fastgpt/service/core/chat/inputGuide/schema';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
export type createChatInputGuideQuery = {};
@@ -19,7 +20,7 @@ async function handler(
res: ApiResponseType<any>
): Promise<createInputGuideResponse> {
const { appId, textList } = req.body;
await authApp({ req, appId, authToken: true, per: 'r' });
await authApp({ req, appId, authToken: true, per: WritePermissionVal });
try {
const result = await MongoChatInputGuide.insertMany(

View File

@@ -1,7 +1,8 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { MongoChatInputGuide } from '@fastgpt/service/core/chat/inputGuide/schema';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
export type deleteChatInputGuideQuery = {};
@@ -14,7 +15,7 @@ async function handler(
res: ApiResponseType<any>
): Promise<deleteInputGuideResponse> {
const { appId, dataIdList } = req.body;
await authApp({ req, appId, authToken: true, per: 'r' });
await authApp({ req, appId, authToken: true, per: ReadPermissionVal });
console.log(dataIdList);
await MongoChatInputGuide.deleteMany({
_id: { $in: dataIdList },

View File

@@ -4,7 +4,8 @@ import { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/t
import { NextAPI } from '@/service/middleware/entry';
import { ApiRequestProps } from '@fastgpt/service/type/next';
import { ChatInputGuideSchemaType } from '@fastgpt/global/core/chat/inputGuide/type';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
export type ChatInputGuideProps = PaginationProps<{
appId: string;
@@ -18,7 +19,7 @@ async function handler(
): Promise<ChatInputGuideResponse> {
const { appId, pageSize, current, searchKey } = req.query;
await authApp({ req, appId, authToken: true, per: 'r' });
await authApp({ req, appId, authToken: true, per: ReadPermissionVal });
const params = {
appId,

View File

@@ -1,7 +1,8 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { MongoChatInputGuide } from '@fastgpt/service/core/chat/inputGuide/schema';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
export type updateChatInputGuideQuery = {};
@@ -18,7 +19,7 @@ async function handler(
res: ApiResponseType<any>
): Promise<updateInputGuideResponse> {
const { appId, dataId, text } = req.body;
await authApp({ req, appId, authToken: true, per: 'r' });
await authApp({ req, appId, authToken: true, per: ReadPermissionVal });
await MongoChatInputGuide.findOneAndUpdate(
{

View File

@@ -3,9 +3,10 @@ import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import { getVectorModel } from '@fastgpt/service/core/ai/model';
import type { DatasetSimpleItemType } from '@fastgpt/global/core/dataset/type.d';
import { mongoRPermission } from '@fastgpt/global/support/permission/utils';
import { authUserRole } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
/* get all dataset by teamId or tmbId */
async function handler(
@@ -13,10 +14,14 @@ async function handler(
res: NextApiResponse<any>
): Promise<DatasetSimpleItemType[]> {
// 凭证校验
const { teamId, tmbId, teamOwner, role } = await authUserRole({ req, authToken: true });
const { teamId, tmbId, permission } = await authUserPer({
req,
authToken: true,
per: ReadPermissionVal
});
const datasets = await MongoDataset.find({
...mongoRPermission({ teamId, tmbId, role }),
...mongoRPermission({ teamId, tmbId, permission }),
type: { $ne: DatasetTypeEnum.folder }
}).lean();

View File

@@ -4,10 +4,11 @@ import { connectToDatabase } from '@/service/mongo';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import type { CreateDatasetParams } from '@/global/core/dataset/api.d';
import { createDefaultCollection } from '@fastgpt/service/core/dataset/collection/controller';
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { getLLMModel, getVectorModel, getDatasetModel } from '@fastgpt/service/core/ai/model';
import { checkTeamDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
@@ -22,7 +23,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
} = req.body as CreateDatasetParams;
// auth
const { teamId, tmbId } = await authUserNotVisitor({ req, authToken: true, authApiKey: true });
const { teamId, tmbId } = await authUserPer({
req,
authToken: true,
authApiKey: true,
per: WritePermissionVal
});
// check model valid
const vectorModelStore = getVectorModel(vectorModel);

View File

@@ -4,21 +4,23 @@ import type { DatasetListItemType } from '@fastgpt/global/core/dataset/type.d';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import { mongoRPermission } from '@fastgpt/global/support/permission/utils';
import { authUserRole } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { getVectorModel } from '@fastgpt/service/core/ai/model';
import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { parentId, type } = req.query as { parentId?: string; type?: DatasetTypeEnum };
// 凭证校验
const { teamId, tmbId, teamOwner, role, canWrite } = await authUserRole({
const { teamId, tmbId, permission } = await authUserPer({
req,
authToken: true,
authApiKey: true
authApiKey: true,
per: ReadPermissionVal
});
const datasets = await MongoDataset.find({
...mongoRPermission({ teamId, tmbId, role }),
...mongoRPermission({ teamId, tmbId, permission }),
...(parentId !== undefined && { parentId: parentId || null }),
...(type && { type })
})
@@ -34,8 +36,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
intro: item.intro,
type: item.type,
permission: item.permission,
canWrite,
isOwner: teamOwner || String(item.tmbId) === tmbId,
canWrite: permission.hasWritePer,
isOwner: permission.isOwner || String(item.tmbId) === tmbId,
vectorModel: getVectorModel(item.vectorModel)
}))
);

View File

@@ -2,15 +2,16 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import type { CreateOnePluginParams } from '@fastgpt/global/core/plugin/controller';
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { MongoPlugin } from '@fastgpt/service/core/plugin/schema';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { httpApiSchema2Plugins } from '@fastgpt/global/core/plugin/httpPlugin/utils';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
await connectToDatabase();
const { teamId, tmbId } = await authUserNotVisitor({ req, authToken: true });
const { teamId, tmbId } = await authUserPer({ req, authToken: true, per: WritePermissionVal });
const body = req.body as CreateOnePluginParams;
// await checkTeamPluginLimit(teamId);

View File

@@ -3,13 +3,14 @@ import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoPlugin } from '@fastgpt/service/core/plugin/schema';
import { authPluginCrud } from '@fastgpt/service/support/permission/auth/plugin';
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
await connectToDatabase();
const { teamId } = await authUserNotVisitor({ req, authToken: true });
const { teamId } = await authUserPer({ req, authToken: true, per: WritePermissionVal });
const { pluginId } = req.query as { pluginId: string };
if (!pluginId) {

View File

@@ -1,13 +1,14 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { pushChatUsage } from '@/service/support/wallet/usage/push';
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { PostWorkflowDebugProps, PostWorkflowDebugResponse } from '@/global/core/workflow/api';
import { authPluginCrud } from '@fastgpt/service/support/permission/auth/plugin';
import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
async function handler(
req: NextApiRequest,
@@ -37,7 +38,7 @@ async function handler(
req,
authToken: true
}),
appId && authApp({ req, authToken: true, appId, per: 'r' }),
appId && authApp({ req, authToken: true, appId, per: ReadPermissionVal }),
pluginId && authPluginCrud({ req, authToken: true, pluginId, per: 'r' })
]);

View File

@@ -4,13 +4,15 @@ import { connectToDatabase } from '@/service/mongo';
import { MongoOpenApi } from '@fastgpt/service/support/openapi/schema';
import { customAlphabet } from 'nanoid';
import type { EditApiKeyProps } from '@/global/support/openapi/api';
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { getNanoid } from '@fastgpt/global/common/string/tools';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { appId, name, limit } = req.body as EditApiKeyProps;
const { teamId, tmbId } = await authUserNotVisitor({ req, authToken: true });
const { teamId, tmbId } = await authUserPer({ req, authToken: true, per: WritePermissionVal });
const count = await MongoOpenApi.find({ tmbId, appId }).countDocuments();
@@ -18,11 +20,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
throw new Error('最多 10 组 API 秘钥');
}
const nanoid = customAlphabet(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
Math.floor(Math.random() * 14) + 52
);
const apiKey = `${global.systemEnv?.openapiPrefix || 'fastgpt'}-${nanoid()}`;
const nanoid = getNanoid(Math.floor(Math.random() * 14) + 52);
const apiKey = `${global.systemEnv?.openapiPrefix || 'fastgpt'}-${nanoid}`;
await MongoOpenApi.create({
teamId,

View File

@@ -3,8 +3,9 @@ import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoOpenApi } from '@fastgpt/service/support/openapi/schema';
import type { GetApiKeyProps } from '@/global/support/openapi/api';
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -12,11 +13,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const { appId } = req.query as GetApiKeyProps;
if (appId) {
const { tmbId, teamOwner } = await authApp({ req, authToken: true, appId, per: 'w' });
await authApp({
req,
authToken: true,
appId,
per: ManagePermissionVal
});
const findResponse = await MongoOpenApi.find({
appId,
...(!teamOwner && { tmbId })
appId
}).sort({ _id: -1 });
return jsonRes(res, {
@@ -24,16 +29,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
}
const {
teamId,
tmbId,
isOwner: teamOwner
} = await authUserNotVisitor({ req, authToken: true });
const { teamId, tmbId, permission } = await authUserPer({
req,
authToken: true,
per: ManagePermissionVal
});
const findResponse = await MongoOpenApi.find({
appId,
teamId,
...(!teamOwner && { tmbId })
...(!permission.isOwner && { tmbId })
}).sort({ _id: -1 });
return jsonRes(res, {

View File

@@ -2,10 +2,11 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import type { OutLinkEditType } from '@fastgpt/global/support/outLink/type.d';
import { customAlphabet } from 'nanoid';
import { PublishChannelEnum } from '@fastgpt/global/support/outLink/constant';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
/* create a shareChat */
@@ -18,7 +19,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
type: PublishChannelEnum;
};
const { teamId, tmbId } = await authApp({ req, authToken: true, appId, per: 'w' });
const { teamId, tmbId } = await authApp({
req,
authToken: true,
appId,
per: WritePermissionVal
});
const shareId = nanoid();
await MongoOutLink.create({

View File

@@ -2,7 +2,8 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { authOutLinkCrud } from '@fastgpt/service/support/permission/auth/outLink';
import { authOutLinkCrud } from '@fastgpt/service/support/permission/publish/authLink';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
/* delete a shareChat by shareChatId */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -13,7 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
id: string;
};
await authOutLinkCrud({ req, outLinkId: id, authToken: true, per: 'owner' });
await authOutLinkCrud({ req, outLinkId: id, authToken: true, per: ManagePermissionVal });
await MongoOutLink.findByIdAndRemove(id);

View File

@@ -2,7 +2,8 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
/* get shareChat list by appId */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -14,11 +15,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
type: string;
};
const { teamId, tmbId, isOwner } = await authApp({ req, authToken: true, appId, per: 'w' });
await authApp({
req,
authToken: true,
appId,
per: ManagePermissionVal
});
const data = await MongoOutLink.find({
appId,
...(isOwner ? { teamId } : { tmbId }),
type: type
}).sort({
_id: -1

View File

@@ -3,7 +3,8 @@ import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import type { OutLinkEditType } from '@fastgpt/global/support/outLink/type.d';
import { authOutLinkCrud } from '@fastgpt/service/support/permission/auth/outLink';
import { authOutLinkCrud } from '@fastgpt/service/support/permission/publish/authLink';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -15,7 +16,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
throw new Error('_id is required');
}
await authOutLinkCrud({ req, outLinkId: _id, authToken: true, per: 'owner' });
await authOutLinkCrud({ req, outLinkId: _id, authToken: true, per: ManagePermissionVal });
await MongoOutLink.findByIdAndUpdate(_id, {
name,

View File

@@ -1,8 +1,9 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { UpdateTeamProps } from '@fastgpt/global/support/user/team/controller';
import { authTeamOwner } from '@fastgpt/service/support/permission/auth/user';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { updateTeam } from '@fastgpt/service/support/user/team/controller';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
export type updateQuery = {};
@@ -13,7 +14,7 @@ export type updateResponse = {};
async function handler(req: ApiRequestProps<updateBody, updateQuery>, res: ApiResponseType<any>) {
const body = req.body as UpdateTeamProps;
const { teamId } = await authTeamOwner({ req, authToken: true });
const { teamId } = await authUserPer({ req, authToken: true, per: ManagePermissionVal });
await updateTeam({ teamId, ...body });
}

View File

@@ -1,5 +1,5 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { sseErrRes, jsonRes } from '@fastgpt/service/common/response';
import { addLog } from '@fastgpt/service/common/system/log';
@@ -47,6 +47,7 @@ import { dispatchWorkFlowV1 } from '@fastgpt/service/core/workflow/dispatchV1';
import { setEntryEntries } from '@fastgpt/service/core/workflow/dispatchV1/utils';
import { NextAPI } from '@/service/middleware/entry';
import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
type FastGptWebChatProps = {
chatId?: string; // undefined: nonuse history, '': new chat, 'xxxxx': use history
@@ -482,17 +483,16 @@ const authHeaderRequest = async ({
if (!appId) {
return Promise.reject('appId is empty');
}
const { app, canWrite } = await authApp({
const { app, permission } = await authApp({
req,
authToken: true,
appId,
per: 'r'
per: ReadPermissionVal
});
return {
app,
canWrite: canWrite
canWrite: permission.hasReadPer
};
}
})();

View File

@@ -7,8 +7,7 @@ import {
Input,
Textarea,
ModalFooter,
ModalBody,
Image
ModalBody
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { AppSchema } from '@fastgpt/global/core/app/type.d';
@@ -19,39 +18,46 @@ import { getErrText } from '@fastgpt/global/common/error/utils';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import Avatar from '@/components/Avatar';
import MyModal from '@fastgpt/web/components/common/MyModal';
import PermissionRadio from '@/components/support/permission/Radio';
import { useTranslation } from 'next-i18next';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
import { AppContext } from '@/web/core/app/context/appContext';
import MemberManager from '@/components/support/permission/MemberManager';
import {
postUpdateAppCollaborators,
deleteAppCollaborators,
getCollaboratorList
} from '@/web/core/app/api/collaborator';
import { useContextSelector } from 'use-context-selector';
import { AppContext } from '@/web/core/app/context/appContext';
import {
AppDefaultPermission,
AppPermissionList
} from '@fastgpt/global/support/permission/app/constant';
import { ReadPermissionVal, WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
import DefaultPermissionList from '@/components/support/permission/DefaultPerList';
const InfoModal = ({
defaultApp,
onClose,
onSuccess
}: {
defaultApp: AppSchema;
onClose: () => void;
onSuccess?: () => void;
}) => {
const InfoModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation();
const { toast } = useToast();
const { updateAppDetail } = useContextSelector(AppContext, (v) => v);
const { updateAppDetail, appDetail } = useContextSelector(AppContext, (v) => v);
const { File, onOpen: onOpenSelectFile } = useSelectFile({
fileType: '.jpg,.png',
multiple: false
});
const {
register,
setValue,
getValues,
formState: { errors },
handleSubmit
handleSubmit,
watch
} = useForm({
defaultValues: defaultApp
defaultValues: appDetail
});
const [refresh, setRefresh] = useState(false);
const defaultPermission = watch('defaultPermission');
const avatar = getValues('avatar');
// submit config
const { mutate: saveSubmitSuccess, isLoading: btnLoading } = useRequest({
@@ -60,11 +66,10 @@ const InfoModal = ({
name: data.name,
avatar: data.avatar,
intro: data.intro,
permission: data.permission
defaultPermission: data.defaultPermission
});
},
onSuccess() {
onSuccess && onSuccess();
onClose();
toast({
title: t('common.Update Success'),
@@ -108,7 +113,6 @@ const InfoModal = ({
maxH: 300
});
setValue('avatar', src);
setRefresh((state) => !state);
} catch (err: any) {
toast({
title: getErrText(err, t('common.error.Select avatar failed')),
@@ -119,6 +123,20 @@ const InfoModal = ({
[setValue, t, toast]
);
const onUpdateCollaborators = async (tmbIds: string[], permission: PermissionValueType) => {
await postUpdateAppCollaborators({
tmbIds,
permission,
appId: appDetail._id
});
};
const onDelCollaborator = async (tmbId: string) => {
await deleteAppCollaborators({
appId: appDetail._id,
tmbId
});
};
return (
<MyModal
isOpen={true}
@@ -130,7 +148,7 @@ const InfoModal = ({
<Box>{t('core.app.Name and avatar')}</Box>
<Flex mt={2} alignItems={'center'}>
<Avatar
src={getValues('avatar')}
src={avatar}
w={['26px', '34px']}
h={['26px', '34px']}
cursor={'pointer'}
@@ -152,9 +170,6 @@ const InfoModal = ({
<Box mt={4} mb={1}>
{t('core.app.App intro')}
</Box>
{/* <Box color={'myGray.500'} mb={2} fontSize={'sm'}>
该介绍主要用于记忆和在应用市场展示
</Box> */}
<Textarea
rows={4}
maxLength={500}
@@ -162,16 +177,32 @@ const InfoModal = ({
bg={'myWhite.600'}
{...register('intro')}
/>
<Box mt={4}>
<Box mb={1}>{t('user.Permission')}</Box>
<PermissionRadio
value={getValues('permission')}
onChange={(e) => {
setValue('permission', e);
setRefresh(!refresh);
}}
/>
</Box>
{/* role */}
{appDetail.permission.hasManagePer && (
<>
{' '}
<Box mt="4">
<Box>{t('permission.Default permission')}</Box>
<DefaultPermissionList
mt="2"
per={defaultPermission}
defaultPer={AppDefaultPermission}
readPer={ReadPermissionVal}
writePer={WritePermissionVal}
onChange={(v) => setValue('defaultPermission', v)}
/>
</Box>
<Box mt={6}>
<MemberManager
onGetCollaboratorList={() => getCollaboratorList(appDetail._id)}
permissionList={AppPermissionList}
onUpdateCollaborators={onUpdateCollaborators}
onDelOneCollaborator={onDelCollaborator}
/>
</Box>
</>
)}
</ModalBody>
<ModalFooter>

View File

@@ -182,16 +182,17 @@ const Share = ({ appId }: { appId: string; type: PublishChannelEnum }) => {
label: t('common.Delete'),
icon: 'delete',
type: 'danger',
onClick: openConfirm(async () => {
setIsLoading(true);
try {
await delShareChatById(item._id);
refetchShareChatList();
} catch (error) {
console.log(error);
}
setIsLoading(false);
})
onClick: () =>
openConfirm(async () => {
setIsLoading(true);
try {
await delShareChatById(item._id);
refetchShareChatList();
} catch (error) {
console.log(error);
}
setIsLoading(false);
})()
}
]}
/>

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Box, Flex, Button, IconButton } from '@chakra-ui/react';
import { Box, Flex, Button, IconButton, useDisclosure } from '@chakra-ui/react';
import { DragHandleIcon } from '@chakra-ui/icons';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
@@ -19,17 +19,23 @@ import { AppContext } from '@/web/core/app/context/appContext';
import { useContextSelector } from 'use-context-selector';
const InfoModal = dynamic(() => import('../InfoModal'));
const AppCard = ({ appId }: { appId: string }) => {
const AppCard = () => {
const router = useRouter();
const { t } = useTranslation();
const { appT } = useI18n();
const { toast } = useToast();
const { appDetail } = useContextSelector(AppContext, (v) => v);
const appId = appDetail._id;
const { feConfigs } = useSystemStore();
const [settingAppInfo, setSettingAppInfo] = useState<AppSchema>();
const [TeamTagsSet, setTeamTagsSet] = useState<AppSchema>();
const {
isOpen: isOpenInfoEdit,
onOpen: onOpenInfoEdit,
onClose: onCloseInfoEdit
} = useDisclosure();
const { openConfirm: openConfirmDel, ConfirmModal: ConfirmDelModal } = useConfirm({
content: appT('Confirm Del App Tip'),
type: 'delete'
@@ -58,7 +64,7 @@ const AppCard = ({ appId }: { appId: string }) => {
<Box px={4}>
<Flex alignItems={'center'} justifyContent={'space-between'}>
<Box fontSize={['md', 'xl']} fontWeight={'bold'}>
<PermissionIconText permission={appDetail.permission} />
<PermissionIconText defaultPermission={appDetail.defaultPermission} />
</Box>
<Box color={'myGray.500'} fontSize={'sm'}>
AppId:{' '}
@@ -83,7 +89,7 @@ const AppCard = ({ appId }: { appId: string }) => {
<Box ml={3} fontWeight={'bold'} fontSize={'lg'}>
{appDetail.name}
</Box>
{appDetail.isOwner && (
{appDetail.permission.isOwner && (
<IconButton
className="delete"
position={'absolute'}
@@ -133,7 +139,7 @@ const AppCard = ({ appId }: { appId: string }) => {
>
{t('core.app.navbar.Publish')}
</Button>
{appDetail.canWrite && feConfigs?.show_team_chat && (
{appDetail.permission.hasWritePer && feConfigs?.show_team_chat && (
<Button
mr={3}
size={['sm', 'md']}
@@ -144,12 +150,12 @@ const AppCard = ({ appId }: { appId: string }) => {
{t('common.Team Tags Set')}
</Button>
)}
{appDetail.isOwner && (
{appDetail.permission.hasManagePer && (
<Button
size={['sm', 'md']}
variant={'whitePrimary'}
leftIcon={<MyIcon name={'common/settingLight'} w={'16px'} />}
onClick={() => setSettingAppInfo(appDetail)}
onClick={onOpenInfoEdit}
>
{t('common.Setting')}
</Button>
@@ -158,9 +164,7 @@ const AppCard = ({ appId }: { appId: string }) => {
</Box>
</Box>
<ConfirmDelModal />
{settingAppInfo && (
<InfoModal defaultApp={settingAppInfo} onClose={() => setSettingAppInfo(undefined)} />
)}
{isOpenInfoEdit && <InfoModal onClose={onCloseInfoEdit} />}
{TeamTagsSet && <TagsEditModal onClose={() => setTeamTagsSet(undefined)} />}
</>
);

View File

@@ -56,7 +56,7 @@ const SimpleEdit = ({ appId }: { appId: string }) => {
pb={10}
overflow={'overlay'}
>
<AppCard appId={appId} />
<AppCard />
<Box mt={2}>
<EditForm editForm={editForm} divRef={divRef} isSticky={isSticky} />

View File

@@ -59,24 +59,25 @@ const AppDetail = ({ appId, currentTab }: { appId: string; currentTab: TabEnum }
id: TabEnum.simpleEdit,
icon: 'common/overviewLight'
},
...(feConfigs?.hide_app_flow
? []
: [
{
label: t('core.app.navbar.Flow mode'),
id: TabEnum.adEdit,
icon: 'core/modules/flowLight'
}
]),
{
label: t('core.app.navbar.Publish app'),
id: TabEnum.publish,
icon: 'support/outlink/shareLight'
label: t('core.app.navbar.Flow mode'),
id: TabEnum.adEdit,
icon: 'core/modules/flowLight'
},
{ label: appT('Chat logs'), id: TabEnum.logs, icon: 'core/app/logsLight' },
...(appDetail.permission.hasManagePer
? [
{
label: t('core.app.navbar.Publish app'),
id: TabEnum.publish,
icon: 'support/outlink/shareLight'
},
{ label: appT('Chat logs'), id: TabEnum.logs, icon: 'core/app/logsLight' }
]
: []),
{ label: t('core.Start chat'), id: TabEnum.startChat, icon: 'core/chat/chatLight' }
],
[appT, feConfigs?.hide_app_flow, t]
[appDetail.permission.hasManagePer, appT, t]
);
const onCloseFlowEdit = useCallback(() => setCurrentTab(TabEnum.simpleEdit), [setCurrentTab]);

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react';
import React, { useCallback } from 'react';
import {
Box,
Flex,
@@ -8,12 +8,8 @@ import {
Input,
Grid,
useTheme,
Card,
Text,
HStack,
Tag
Card
} from '@chakra-ui/react';
import { AddIcon } from '@chakra-ui/icons';
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { useForm } from 'react-hook-form';
import { compressImgFileAndUpload } from '@/web/common/file/controller';
@@ -136,52 +132,48 @@ const CreateModal = ({ onClose, onSuccess }: { onClose: () => void; onSuccess: (
})}
/>
</Flex>
{!feConfigs?.hide_app_flow && (
<>
<Box mt={[4, 7]} mb={[0, 3]} color={'myGray.800'} fontWeight={'bold'}>
{t('core.app.Select app from template')}
</Box>
<Grid
userSelect={'none'}
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)']}
gridGap={[2, 4]}
<Box mt={[4, 7]} mb={[0, 3]} color={'myGray.800'} fontWeight={'bold'}>
{t('core.app.Select app from template')}
</Box>
<Grid
userSelect={'none'}
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)']}
gridGap={[2, 4]}
>
{appTemplates.map((item) => (
<Card
key={item.id}
border={theme.borders.base}
p={3}
borderRadius={'md'}
cursor={'pointer'}
boxShadow={'sm'}
{...(templateId === item.id
? {
bg: 'primary.50',
borderColor: 'primary.500'
}
: {
_hover: {
boxShadow: 'md'
}
})}
onClick={() => {
setValue('templateId', item.id);
}}
>
{appTemplates.map((item) => (
<Card
key={item.id}
border={theme.borders.base}
p={3}
borderRadius={'md'}
cursor={'pointer'}
boxShadow={'sm'}
{...(templateId === item.id
? {
bg: 'primary.50',
borderColor: 'primary.500'
}
: {
_hover: {
boxShadow: 'md'
}
})}
onClick={() => {
setValue('templateId', item.id);
}}
>
<Flex alignItems={'center'}>
<Avatar src={item.avatar} borderRadius={'md'} w={'20px'} />
<Box ml={3} fontWeight={'bold'}>
{t(item.name)}
</Box>
</Flex>
<Box fontSize={'sm'} mt={4}>
{t(item.intro)}
</Box>
</Card>
))}
</Grid>
</>
)}
<Flex alignItems={'center'}>
<Avatar src={item.avatar} borderRadius={'md'} w={'20px'} />
<Box ml={3} fontWeight={'bold'}>
{t(item.name)}
</Box>
</Flex>
<Box fontSize={'sm'} mt={4}>
{t(item.intro)}
</Box>
</Card>
))}
</Grid>
</ModalBody>
<ModalFooter>

View File

@@ -27,7 +27,7 @@ const MyApps = () => {
const { userInfo } = useUserStore();
const { myApps, loadMyApps } = useAppStore();
const { openConfirm, ConfirmModal } = useConfirm({
title: '删除提示',
type: 'delete',
content: '确认删除该应用所有信息?'
});
const {
@@ -67,9 +67,11 @@ const MyApps = () => {
<Box letterSpacing={1} fontSize={['20px', '24px']} color={'myGray.900'}>
{appT('My Apps')}
</Box>
<Button leftIcon={<AddIcon />} variant={'primaryOutline'} onClick={onOpenCreateModal}>
{commonT('New Create')}
</Button>
{userInfo?.team.permission.hasWritePer && (
<Button leftIcon={<AddIcon />} variant={'primaryOutline'} onClick={onOpenCreateModal}>
{commonT('New Create')}
</Button>
)}
</Flex>
<Grid
py={[4, 6]}
@@ -79,7 +81,7 @@ const MyApps = () => {
{myApps.map((app) => (
<MyTooltip
key={app._id}
label={userInfo?.team.canWrite ? appT('To Settings') : appT('To Chat')}
label={app.permission.hasWritePer ? appT('To Settings') : appT('To Chat')}
>
<Box
lineHeight={1.5}
@@ -106,7 +108,7 @@ const MyApps = () => {
}
}}
onClick={() => {
if (userInfo?.team.canWrite) {
if (app.permission.hasWritePer) {
router.push(`/app/detail?appId=${app._id}`);
} else {
router.push(`/chat?appId=${app._id}`);
@@ -116,7 +118,7 @@ const MyApps = () => {
<Flex alignItems={'center'} h={'38px'}>
<Avatar src={app.avatar} borderRadius={'md'} w={'28px'} />
<Box ml={3}>{app.name}</Box>
{app.isOwner && userInfo?.team.canWrite && (
{app.permission.isOwner && (
<IconButton
className="delete"
position={'absolute'}
@@ -146,9 +148,12 @@ const MyApps = () => {
</Box>
<Flex h={'34px'} alignItems={'flex-end'}>
<Box flex={1}>
<PermissionIconText permission={app.permission} color={'myGray.600'} />
<PermissionIconText
defaultPermission={app.defaultPermission}
color={'myGray.600'}
/>
</Box>
{userInfo?.team.canWrite && (
{app.permission.hasWritePer && (
<IconButton
className="chat"
size={'xsSquare'}

View File

@@ -41,7 +41,7 @@ const Slider = ({ currentTab }: { currentTab: TabEnum }) => {
icon: 'common/overviewLight'
},
{ label: t('core.dataset.test.Search Test'), id: TabEnum.test, icon: 'kbTest' },
...(userInfo?.team.canWrite && datasetDetail.isOwner
...(userInfo?.team.permission.hasWritePer && datasetDetail.isOwner
? [{ label: t('common.Config'), id: TabEnum.info, icon: 'common/settingLight' }]
: [])
];

View File

@@ -168,7 +168,7 @@ const Dataset = () => {
}}
/>
{/* create icon */}
{userInfo?.team?.canWrite && (
{userInfo?.team?.permission.hasWritePer && (
<MyMenu
offset={[-30, 5]}
width={120}
@@ -276,7 +276,7 @@ const Dataset = () => {
}
}}
>
{userInfo?.team.canWrite && dataset.isOwner && (
{userInfo?.team?.permission.hasWritePer && dataset.isOwner && (
<Box
position={'absolute'}
top={3}

View File

@@ -75,7 +75,7 @@ const TeamPlugins = () => {
});
}}
/>
{userInfo?.team?.canWrite && (
{userInfo?.team?.permission.hasWritePer && (
<MyMenu
offset={[-30, 5]}
width={120}