mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
V4.8.17 feature (#3485)
* feat: add third party account config (#3443) * temp * editor workflow variable style * add team to dispatch * i18n * delete console * change openai account position * fix * fix * fix * fix * fix * 4.8.17 test (#3461) * perf: external provider config * perf: ui * feat: add template config (#3434) * change template position * template config * delete console * delete * fix * fix * perf: Mongo visutal field (#3464) * remve invalid code * perf: team member visutal code * perf: virtual search; perf: search test data * fix: ts * fix: image response headers * perf: template code * perf: auth layout;perf: auto save (#3472) * perf: auth layout * perf: auto save * perf: auto save * fix: template guide display & http input support external variables (#3475) * fix: template guide display * http editor support external workflow variables * perf: auto save;fix: ifelse checker line break; (#3478) * perf: auto save * perf: auto save * fix: ifelse checker line break * perf: doc * perf: doc * fix: update var type error * 4.8.17 test (#3479) * perf: auto save * perf: auto save * perf: template code * 4.8.17 test (#3480) * perf: auto save * perf: auto save * perf: model price model * feat: add react memo * perf: model provider filter * fix: ts (#3481) * perf: auto save * perf: auto save * fix: ts * simple app tool select (#3473) * workflow plugin userguide & simple tool ui * simple tool filter * reuse component * change component to hook * fix * perf: too selector modal (#3484) * perf: auto save * perf: auto save * perf: markdown render * perf: too selector * fix: app version require tmbId * perf: templates refresh * perf: templates refresh * hide auto save error tip * perf: toolkit guide --------- Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
@@ -83,6 +83,13 @@ const OutLinkSchema = new Schema({
|
||||
}
|
||||
});
|
||||
|
||||
OutLinkSchema.virtual('associatedApp', {
|
||||
ref: AppCollectionName,
|
||||
localField: 'appId',
|
||||
foreignField: '_id',
|
||||
justOne: true
|
||||
});
|
||||
|
||||
try {
|
||||
OutLinkSchema.index({ shareId: -1 });
|
||||
} catch (error) {
|
||||
|
@@ -1,18 +1,32 @@
|
||||
import { TeamMemberWithUserSchema } from '@fastgpt/global/support/user/team/type';
|
||||
import { MongoTeamMember } from '../../user/team/teamMemberSchema';
|
||||
import { checkTeamAIPoints } from '../teamLimit';
|
||||
import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
|
||||
import { UserModelSchema } from '@fastgpt/global/support/user/type';
|
||||
import { TeamSchema } from '@fastgpt/global/support/user/team/type';
|
||||
|
||||
export async function getUserChatInfoAndAuthTeamPoints(tmbId: string) {
|
||||
const tmb = (await MongoTeamMember.findById(tmbId, 'teamId userId').populate(
|
||||
'userId',
|
||||
'timezone openaiAccount'
|
||||
)) as TeamMemberWithUserSchema;
|
||||
const tmb = await MongoTeamMember.findById(tmbId, 'userId teamId')
|
||||
.populate<{ user: UserModelSchema; team: TeamSchema }>([
|
||||
{
|
||||
path: 'user',
|
||||
select: 'timezone'
|
||||
},
|
||||
{
|
||||
path: 'team',
|
||||
select: 'openaiAccount externalWorkflowVariables'
|
||||
}
|
||||
])
|
||||
.lean();
|
||||
|
||||
if (!tmb) return Promise.reject(UserErrEnum.unAuthUser);
|
||||
|
||||
await checkTeamAIPoints(tmb.teamId);
|
||||
await checkTeamAIPoints(tmb.team._id);
|
||||
|
||||
return {
|
||||
user: tmb.userId
|
||||
timezone: tmb.user.timezone,
|
||||
externalProvider: {
|
||||
openaiAccount: tmb.team.openaiAccount,
|
||||
externalWorkflowVariables: tmb.team.externalWorkflowVariables
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -10,17 +10,17 @@ import { MongoResourcePermission } from './schema';
|
||||
import { ClientSession } from 'mongoose';
|
||||
import {
|
||||
PermissionValueType,
|
||||
ResourcePermissionType,
|
||||
ResourcePerWithGroup,
|
||||
ResourcePerWithTmbWithUser
|
||||
ResourcePermissionType
|
||||
} from '@fastgpt/global/support/permission/type';
|
||||
import { bucketNameMap } from '@fastgpt/global/common/file/constants';
|
||||
import { addMinutes } from 'date-fns';
|
||||
import { getGroupsByTmbId } from './memberGroup/controllers';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { RequireOnlyOne } from '@fastgpt/global/common/type/utils';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { MemberGroupSchemaType } from '@fastgpt/global/support/permission/memberGroup/type';
|
||||
import { TeamMemberSchema } from '@fastgpt/global/support/user/team/type';
|
||||
import { UserModelSchema } from '@fastgpt/global/support/user/type';
|
||||
|
||||
/** get resource permission for a team member
|
||||
* If there is no permission for the team member, it will return undefined
|
||||
@@ -160,32 +160,33 @@ export const getClbsAndGroupsWithInfo = async ({
|
||||
teamId: string;
|
||||
}) =>
|
||||
Promise.all([
|
||||
(await MongoResourcePermission.find({
|
||||
MongoResourcePermission.find({
|
||||
teamId,
|
||||
resourceId,
|
||||
resourceType,
|
||||
tmbId: {
|
||||
$exists: true
|
||||
}
|
||||
}).populate({
|
||||
path: 'tmbId',
|
||||
select: 'name userId',
|
||||
populate: {
|
||||
path: 'userId',
|
||||
select: 'avatar'
|
||||
}
|
||||
})) as ResourcePerWithTmbWithUser[],
|
||||
(await MongoResourcePermission.find({
|
||||
})
|
||||
.populate<{ tmb: TeamMemberSchema & { user: UserModelSchema } }>({
|
||||
path: 'tmb',
|
||||
select: 'name userId',
|
||||
populate: {
|
||||
path: 'user',
|
||||
select: 'avatar'
|
||||
}
|
||||
})
|
||||
.lean(),
|
||||
MongoResourcePermission.find({
|
||||
teamId,
|
||||
resourceId,
|
||||
resourceType,
|
||||
groupId: {
|
||||
$exists: true
|
||||
}
|
||||
}).populate({
|
||||
path: 'groupId',
|
||||
select: 'name avatar'
|
||||
})) as ResourcePerWithGroup[]
|
||||
})
|
||||
.populate<{ group: MemberGroupSchemaType }>('group', 'name avatar')
|
||||
.lean()
|
||||
]);
|
||||
|
||||
export const delResourcePermissionById = (id: string) => {
|
||||
|
@@ -3,7 +3,6 @@ import { getResourcePermission, parseHeaderCert } from '../controller';
|
||||
import {
|
||||
CollectionWithDatasetType,
|
||||
DatasetDataItemType,
|
||||
DatasetFileSchema,
|
||||
DatasetSchemaType
|
||||
} from '@fastgpt/global/core/dataset/type';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
@@ -12,10 +11,6 @@ import { NullPermission, PerResourceTypeEnum } from '@fastgpt/global/support/per
|
||||
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
|
||||
import { DatasetPermission } from '@fastgpt/global/support/permission/dataset/controller';
|
||||
import { getCollectionWithDataset } from '../../../core/dataset/controller';
|
||||
import { MongoDatasetCollection } from '../../../core/dataset/collection/schema';
|
||||
import { getFileById } from '../../../common/file/gridfs/controller';
|
||||
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { MongoDatasetData } from '../../../core/dataset/data/schema';
|
||||
import { AuthModeType, AuthResponseType } from '../type';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
@@ -181,7 +176,7 @@ export async function authDatasetCollection({
|
||||
|
||||
const { dataset } = await authDatasetByTmbId({
|
||||
tmbId,
|
||||
datasetId: collection.datasetId._id,
|
||||
datasetId: collection.datasetId,
|
||||
per,
|
||||
isRoot: isRootFromHeader
|
||||
});
|
||||
|
@@ -66,48 +66,19 @@ export const getGroupsByTmbId = async ({
|
||||
},
|
||||
...(role ? { role: { $in: role } } : {})
|
||||
})
|
||||
.populate('groupId')
|
||||
.populate<{ group: MemberGroupSchemaType }>('group')
|
||||
.lean()
|
||||
).map((item) => {
|
||||
return {
|
||||
...(item.groupId as any as MemberGroupSchemaType)
|
||||
};
|
||||
}),
|
||||
|
||||
).map((item) => item.group),
|
||||
role ? [] : getTeamDefaultGroup({ teamId })
|
||||
])
|
||||
).flat();
|
||||
|
||||
export const getTmbByGroupId = async (groupId: string) => {
|
||||
return (
|
||||
await MongoGroupMemberModel.find({
|
||||
groupId
|
||||
})
|
||||
.populate('tmbId')
|
||||
.lean()
|
||||
).map((item) => {
|
||||
return {
|
||||
...(item.tmbId as any as MemberGroupSchemaType)
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const getGroupMembersByGroupId = async (groupId: string) => {
|
||||
return await MongoGroupMemberModel.find({
|
||||
groupId
|
||||
}).lean();
|
||||
};
|
||||
|
||||
export const getGroupMembersWithInfoByGroupId = async (groupId: string) => {
|
||||
return (
|
||||
await MongoGroupMemberModel.find({
|
||||
groupId
|
||||
})
|
||||
.populate('tmbId')
|
||||
.lean()
|
||||
).map((item) => item.tmbId) as any as TeamMemberSchema[]; // HACK: type casting
|
||||
};
|
||||
|
||||
/**
|
||||
* Get tmb's group permission: the maximum permission of the group
|
||||
* @param tmbId
|
||||
|
@@ -26,6 +26,13 @@ export const GroupMemberSchema = new Schema({
|
||||
}
|
||||
});
|
||||
|
||||
GroupMemberSchema.virtual('group', {
|
||||
ref: MemberGroupCollectionName,
|
||||
localField: 'groupId',
|
||||
foreignField: '_id',
|
||||
justOne: true
|
||||
});
|
||||
|
||||
try {
|
||||
GroupMemberSchema.index({
|
||||
groupId: 1
|
||||
|
@@ -39,6 +39,19 @@ export const ResourcePermissionSchema = new Schema({
|
||||
}
|
||||
});
|
||||
|
||||
ResourcePermissionSchema.virtual('tmb', {
|
||||
ref: TeamMemberCollectionName,
|
||||
localField: 'tmbId',
|
||||
foreignField: '_id',
|
||||
justOne: true
|
||||
});
|
||||
ResourcePermissionSchema.virtual('group', {
|
||||
ref: MemberGroupCollectionName,
|
||||
localField: 'groupId',
|
||||
foreignField: '_id',
|
||||
justOne: true
|
||||
});
|
||||
|
||||
try {
|
||||
ResourcePermissionSchema.index(
|
||||
{
|
||||
|
@@ -44,7 +44,6 @@ export async function getUserDetail({
|
||||
avatar: user.avatar,
|
||||
timezone: user.timezone,
|
||||
promotionRate: user.promotionRate,
|
||||
openaiAccount: user.openaiAccount,
|
||||
team: tmb,
|
||||
notificationAccount: tmb.notificationAccount,
|
||||
permission: tmb.permission
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { TeamTmbItemType, TeamMemberWithTeamSchema } from '@fastgpt/global/support/user/team/type';
|
||||
import { TeamSchema, TeamTmbItemType } from '@fastgpt/global/support/user/team/type';
|
||||
import { ClientSession, Types } from '../../../common/mongo';
|
||||
import {
|
||||
TeamMemberRoleEnum,
|
||||
@@ -15,37 +15,41 @@ import { TeamDefaultPermissionVal } from '@fastgpt/global/support/permission/use
|
||||
import { MongoMemberGroupModel } from '../../permission/memberGroup/memberGroupSchema';
|
||||
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
|
||||
import { DefaultGroupName } from '@fastgpt/global/support/user/team/group/constant';
|
||||
import { getAIApi, openaiBaseUrl } from '../../../core/ai/config';
|
||||
|
||||
async function getTeamMember(match: Record<string, any>): Promise<TeamTmbItemType> {
|
||||
const tmb = (await MongoTeamMember.findOne(match).populate('teamId')) as TeamMemberWithTeamSchema;
|
||||
const tmb = await MongoTeamMember.findOne(match).populate<{ team: TeamSchema }>('team').lean();
|
||||
if (!tmb) {
|
||||
return Promise.reject('member not exist');
|
||||
}
|
||||
|
||||
const Per = await getResourcePermission({
|
||||
resourceType: PerResourceTypeEnum.team,
|
||||
teamId: tmb.teamId._id,
|
||||
teamId: tmb.teamId,
|
||||
tmbId: tmb._id
|
||||
});
|
||||
|
||||
return {
|
||||
userId: String(tmb.userId),
|
||||
teamId: String(tmb.teamId._id),
|
||||
teamName: tmb.teamId.name,
|
||||
teamId: String(tmb.teamId),
|
||||
teamName: tmb.team.name,
|
||||
memberName: tmb.name,
|
||||
avatar: tmb.teamId.avatar,
|
||||
balance: tmb.teamId.balance,
|
||||
avatar: tmb.team.avatar,
|
||||
balance: tmb.team.balance,
|
||||
tmbId: String(tmb._id),
|
||||
teamDomain: tmb.teamId?.teamDomain,
|
||||
teamDomain: tmb.team?.teamDomain,
|
||||
role: tmb.role,
|
||||
status: tmb.status,
|
||||
defaultTeam: tmb.defaultTeam,
|
||||
lafAccount: tmb.teamId.lafAccount,
|
||||
permission: new TeamPermission({
|
||||
per: Per ?? TeamDefaultPermissionVal,
|
||||
isOwner: tmb.role === TeamMemberRoleEnum.owner
|
||||
}),
|
||||
notificationAccount: tmb.teamId.notificationAccount
|
||||
notificationAccount: tmb.team.notificationAccount,
|
||||
|
||||
lafAccount: tmb.team.lafAccount,
|
||||
openaiAccount: tmb.team.openaiAccount,
|
||||
externalWorkflowVariables: tmb.team.externalWorkflowVariables
|
||||
};
|
||||
}
|
||||
|
||||
@@ -145,21 +149,87 @@ export async function updateTeam({
|
||||
name,
|
||||
avatar,
|
||||
teamDomain,
|
||||
lafAccount
|
||||
lafAccount,
|
||||
openaiAccount,
|
||||
externalWorkflowVariable
|
||||
}: UpdateTeamProps & { teamId: string }) {
|
||||
// auth openai key
|
||||
if (openaiAccount?.key) {
|
||||
console.log('auth user openai key', openaiAccount?.key);
|
||||
const baseUrl = openaiAccount?.baseUrl || openaiBaseUrl;
|
||||
openaiAccount.baseUrl = baseUrl;
|
||||
|
||||
const ai = getAIApi({
|
||||
userKey: openaiAccount
|
||||
});
|
||||
|
||||
const response = await ai.chat.completions.create({
|
||||
model: 'gpt-4o-mini',
|
||||
max_tokens: 1,
|
||||
messages: [{ role: 'user', content: 'hi' }]
|
||||
});
|
||||
if (response?.choices?.[0]?.message?.content === undefined) {
|
||||
return Promise.reject('Key response is empty');
|
||||
}
|
||||
}
|
||||
|
||||
return mongoSessionRun(async (session) => {
|
||||
const unsetObj = (() => {
|
||||
const obj: Record<string, 1> = {};
|
||||
if (lafAccount?.pat === '') {
|
||||
obj.lafAccount = 1;
|
||||
}
|
||||
if (openaiAccount?.key === '') {
|
||||
obj.openaiAccount = 1;
|
||||
}
|
||||
if (externalWorkflowVariable) {
|
||||
if (externalWorkflowVariable.value === '') {
|
||||
obj[`externalWorkflowVariables.${externalWorkflowVariable.key}`] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(obj).length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
$unset: obj
|
||||
};
|
||||
})();
|
||||
const setObj = (() => {
|
||||
const obj: Record<string, any> = {};
|
||||
if (lafAccount?.pat && lafAccount?.appid) {
|
||||
obj.lafAccount = lafAccount;
|
||||
}
|
||||
if (openaiAccount?.key && openaiAccount?.baseUrl) {
|
||||
obj.openaiAccount = openaiAccount;
|
||||
}
|
||||
if (externalWorkflowVariable) {
|
||||
if (externalWorkflowVariable.value !== '') {
|
||||
obj[`externalWorkflowVariables.${externalWorkflowVariable.key}`] =
|
||||
externalWorkflowVariable.value;
|
||||
}
|
||||
}
|
||||
if (Object.keys(obj).length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return obj;
|
||||
})();
|
||||
|
||||
await MongoTeam.findByIdAndUpdate(
|
||||
teamId,
|
||||
{
|
||||
name,
|
||||
avatar,
|
||||
teamDomain,
|
||||
lafAccount
|
||||
$set: {
|
||||
...(name ? { name } : {}),
|
||||
...(avatar ? { avatar } : {}),
|
||||
...(teamDomain ? { teamDomain } : {}),
|
||||
...setObj
|
||||
},
|
||||
...unsetObj
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
|
||||
// update default group
|
||||
// Update member group avatar
|
||||
if (avatar) {
|
||||
await MongoMemberGroupModel.updateOne(
|
||||
{
|
||||
|
@@ -3,7 +3,6 @@ const { Schema } = connectionMongo;
|
||||
import { TeamMemberSchema as TeamMemberType } from '@fastgpt/global/support/user/team/type.d';
|
||||
import { userCollectionName } from '../../user/schema';
|
||||
import {
|
||||
TeamMemberRoleMap,
|
||||
TeamMemberStatusMap,
|
||||
TeamMemberCollectionName,
|
||||
TeamCollectionName
|
||||
@@ -42,6 +41,19 @@ const TeamMemberSchema = new Schema({
|
||||
}
|
||||
});
|
||||
|
||||
TeamMemberSchema.virtual('team', {
|
||||
ref: TeamCollectionName,
|
||||
localField: 'teamId',
|
||||
foreignField: '_id',
|
||||
justOne: true
|
||||
});
|
||||
TeamMemberSchema.virtual('user', {
|
||||
ref: userCollectionName,
|
||||
localField: 'userId',
|
||||
foreignField: '_id',
|
||||
justOne: true
|
||||
});
|
||||
|
||||
try {
|
||||
TeamMemberSchema.index({ teamId: 1 }, { background: true });
|
||||
TeamMemberSchema.index({ userId: 1 }, { background: true });
|
||||
|
@@ -47,6 +47,16 @@ const TeamSchema = new Schema({
|
||||
type: String
|
||||
}
|
||||
},
|
||||
openaiAccount: {
|
||||
type: {
|
||||
key: String,
|
||||
baseUrl: String
|
||||
}
|
||||
},
|
||||
externalWorkflowVariables: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
notificationAccount: {
|
||||
type: String,
|
||||
required: false
|
||||
|
Reference in New Issue
Block a user