mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-02 12:48:30 +00:00
v4.6 -1 (#459)
This commit is contained in:
14
projects/app/src/service/support/outLink/auth.ts
Normal file
14
projects/app/src/service/support/outLink/auth.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
||||
import type {
|
||||
AuthLinkLimitProps,
|
||||
AuthShareChatInitProps
|
||||
} from '@fastgpt/global/support/outLink/api.d';
|
||||
|
||||
export function authOutLinkLimit(data: AuthLinkLimitProps) {
|
||||
return POST('/support/outLink/authLimit', data);
|
||||
}
|
||||
|
||||
export function authShareChatInit(data: AuthShareChatInitProps) {
|
||||
if (!global.feConfigs?.isPlus) return;
|
||||
return POST('/support/outLink/authShareChatInit', data);
|
||||
}
|
8
projects/app/src/service/support/permission/auth/bill.ts
Normal file
8
projects/app/src/service/support/permission/auth/bill.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { GET } from '@fastgpt/service/common/api/plusRequest';
|
||||
|
||||
export const authTeamBalance = async (teamId: string) => {
|
||||
if (global.systemEnv.pluginBaseUrl) {
|
||||
return GET('/support/permission/authBalance', { teamId });
|
||||
}
|
||||
return true;
|
||||
};
|
36
projects/app/src/service/support/permission/auth/dataset.ts
Normal file
36
projects/app/src/service/support/permission/auth/dataset.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { getDatasetPgData } from '@/service/core/dataset/data/controller';
|
||||
import { PgDataItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
|
||||
import { authDatasetCollection } from '@fastgpt/service/support/permission/auth/dataset';
|
||||
import { parseHeaderCert } from '@fastgpt/service/support/permission/controller';
|
||||
import { AuthModeType } from '@fastgpt/service/support/permission/type';
|
||||
|
||||
export async function authDatasetData({
|
||||
dataId,
|
||||
...props
|
||||
}: AuthModeType & {
|
||||
dataId: string;
|
||||
}): Promise<
|
||||
AuthResponseType & {
|
||||
datasetData: PgDataItemType;
|
||||
}
|
||||
> {
|
||||
const result = await parseHeaderCert(props);
|
||||
const { tmbId } = result;
|
||||
// get pg data
|
||||
const datasetData = await getDatasetPgData({ id: dataId });
|
||||
|
||||
const isOwner = String(datasetData.tmbId) === tmbId;
|
||||
// data has the same permissions as collection
|
||||
const { canWrite } = await authDatasetCollection({
|
||||
...props,
|
||||
collectionId: datasetData.collectionId
|
||||
});
|
||||
|
||||
return {
|
||||
...result,
|
||||
datasetData,
|
||||
isOwner,
|
||||
canWrite
|
||||
};
|
||||
}
|
31
projects/app/src/service/support/permission/auth/outLink.ts
Normal file
31
projects/app/src/service/support/permission/auth/outLink.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { authOutLinkLimit } from '@/service/support/outLink/auth';
|
||||
import { AuthLinkChatProps } from '@fastgpt/global/support/outLink/api.d';
|
||||
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { getUserAndAuthBalance } from './user';
|
||||
import { authOutLinkValid } from '@fastgpt/service/support/permission/auth/outLink';
|
||||
|
||||
export async function authOutLinkChat({
|
||||
shareId,
|
||||
ip,
|
||||
authToken,
|
||||
question
|
||||
}: AuthLinkChatProps & {
|
||||
shareId: string;
|
||||
}) {
|
||||
// get outLink
|
||||
const { shareChat, app } = await authOutLinkValid({ shareId });
|
||||
|
||||
const [user] = await Promise.all([
|
||||
getUserAndAuthBalance({ tmbId: shareChat.tmbId, minBalance: 0 }),
|
||||
global.feConfigs?.isPlus
|
||||
? authOutLinkLimit({ outLink: shareChat, ip, authToken, question })
|
||||
: undefined
|
||||
]);
|
||||
|
||||
return {
|
||||
authType: AuthUserTypeEnum.token,
|
||||
responseDetail: shareChat.responseDetail,
|
||||
user,
|
||||
app
|
||||
};
|
||||
}
|
48
projects/app/src/service/support/permission/auth/user.ts
Normal file
48
projects/app/src/service/support/permission/auth/user.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
|
||||
import { parseHeaderCert } from '@fastgpt/service/support/permission/controller';
|
||||
import { AuthModeType } from '@fastgpt/service/support/permission/type';
|
||||
import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
|
||||
import { UserType } from '@fastgpt/global/support/user/type';
|
||||
import { getUserDetail } from '@/service/support/user/controller';
|
||||
|
||||
export async function getUserAndAuthBalance({
|
||||
tmbId,
|
||||
minBalance
|
||||
}: {
|
||||
tmbId: string;
|
||||
minBalance?: number;
|
||||
}) {
|
||||
const user = await getUserDetail({ tmbId });
|
||||
|
||||
if (!user) {
|
||||
return Promise.reject(UserErrEnum.unAuthUser);
|
||||
}
|
||||
if (minBalance !== undefined && global.feConfigs.isPlus && user.team.balance < minBalance) {
|
||||
return Promise.reject(UserErrEnum.balanceNotEnough);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/* get user */
|
||||
export async function authUser({
|
||||
minBalance,
|
||||
...props
|
||||
}: AuthModeType & {
|
||||
minBalance?: number;
|
||||
}): Promise<
|
||||
AuthResponseType & {
|
||||
user: UserType;
|
||||
}
|
||||
> {
|
||||
const { userId, teamId, tmbId } = await parseHeaderCert(props);
|
||||
|
||||
return {
|
||||
userId,
|
||||
teamId,
|
||||
tmbId,
|
||||
user: await getUserAndAuthBalance({ tmbId, minBalance }),
|
||||
isOwner: true,
|
||||
canWrite: true
|
||||
};
|
||||
}
|
30
projects/app/src/service/support/user/controller.ts
Normal file
30
projects/app/src/service/support/user/controller.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { ERROR_ENUM } from '@fastgpt/global/common/error/errorCode';
|
||||
import { MongoUser } from '@fastgpt/service/support/user/schema';
|
||||
import { UserType } from '@fastgpt/global/support/user/type';
|
||||
import { getTeamInfoByTmbId } from '@fastgpt/service/support/user/team/controller';
|
||||
|
||||
export async function getUserDetail({
|
||||
tmbId,
|
||||
userId
|
||||
}: {
|
||||
tmbId?: string;
|
||||
userId?: string;
|
||||
}): Promise<UserType> {
|
||||
const team = await getTeamInfoByTmbId({ tmbId, userId });
|
||||
const user = await MongoUser.findById(team.userId);
|
||||
|
||||
if (!user) {
|
||||
return Promise.reject(ERROR_ENUM.unAuthorization);
|
||||
}
|
||||
|
||||
return {
|
||||
_id: user._id,
|
||||
username: user.username,
|
||||
avatar: user.avatar,
|
||||
balance: user.balance,
|
||||
timezone: user.timezone,
|
||||
promotionRate: user.promotionRate,
|
||||
openaiAccount: user.openaiAccount,
|
||||
team
|
||||
};
|
||||
}
|
7
projects/app/src/service/support/user/inform/api.ts
Normal file
7
projects/app/src/service/support/user/inform/api.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
||||
import { SendInformProps } from '@fastgpt/global/support/user/inform/type';
|
||||
|
||||
export function sendOneInform(data: SendInformProps) {
|
||||
if (!global.systemEnv.pluginBaseUrl) return;
|
||||
return POST('/support/user/inform/create', data);
|
||||
}
|
201
projects/app/src/service/support/wallet/bill/push.ts
Normal file
201
projects/app/src/service/support/wallet/bill/push.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||
import { getAudioSpeechModel, getModelMap, ModelTypeEnum } from '@/service/core/ai/model';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { addLog } from '@fastgpt/service/common/mongo/controller';
|
||||
import type { ConcatBillProps, CreateBillProps } from '@fastgpt/global/support/wallet/bill/api.d';
|
||||
import { defaultQGModels } from '@fastgpt/global/core/ai/model';
|
||||
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
||||
|
||||
export function createBill(data: CreateBillProps) {
|
||||
if (!global.systemEnv.pluginBaseUrl) return;
|
||||
POST('/support/wallet/bill/createBill', data);
|
||||
}
|
||||
export function concatBill(data: ConcatBillProps) {
|
||||
if (!global.systemEnv.pluginBaseUrl) return;
|
||||
POST('/support/wallet/bill/concatBill', data);
|
||||
}
|
||||
|
||||
export const pushChatBill = ({
|
||||
appName,
|
||||
appId,
|
||||
teamId,
|
||||
tmbId,
|
||||
source,
|
||||
response
|
||||
}: {
|
||||
appName: string;
|
||||
appId: string;
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
source: `${BillSourceEnum}`;
|
||||
response: ChatHistoryItemResType[];
|
||||
}) => {
|
||||
const total = response.reduce((sum, item) => sum + item.price, 0);
|
||||
|
||||
createBill({
|
||||
teamId,
|
||||
tmbId,
|
||||
appName,
|
||||
appId,
|
||||
total,
|
||||
source,
|
||||
list: response.map((item) => ({
|
||||
moduleName: item.moduleName,
|
||||
amount: item.price || 0,
|
||||
model: item.model,
|
||||
tokenLen: item.tokens
|
||||
}))
|
||||
});
|
||||
addLog.info(`finish completions`, {
|
||||
source,
|
||||
teamId,
|
||||
tmbId,
|
||||
price: formatPrice(total)
|
||||
});
|
||||
return { total };
|
||||
};
|
||||
|
||||
export const pushQABill = async ({
|
||||
teamId,
|
||||
tmbId,
|
||||
totalTokens,
|
||||
billId
|
||||
}: {
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
totalTokens: number;
|
||||
billId: string;
|
||||
}) => {
|
||||
addLog.info('splitData generate success', { totalTokens });
|
||||
|
||||
// 获取模型单价格
|
||||
const unitPrice = global.qaModels?.[0]?.price || 3;
|
||||
// 计算价格
|
||||
const total = unitPrice * totalTokens;
|
||||
|
||||
concatBill({
|
||||
billId,
|
||||
teamId,
|
||||
tmbId,
|
||||
total,
|
||||
tokens: totalTokens,
|
||||
listIndex: 1
|
||||
});
|
||||
|
||||
return { total };
|
||||
};
|
||||
|
||||
export const pushGenerateVectorBill = async ({
|
||||
billId,
|
||||
teamId,
|
||||
tmbId,
|
||||
tokenLen,
|
||||
model,
|
||||
source = BillSourceEnum.fastgpt
|
||||
}: {
|
||||
billId?: string;
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
tokenLen: number;
|
||||
model: string;
|
||||
source?: `${BillSourceEnum}`;
|
||||
}) => {
|
||||
// 计算价格. 至少为1
|
||||
const vectorModel =
|
||||
global.vectorModels.find((item) => item.model === model) || global.vectorModels[0];
|
||||
const unitPrice = vectorModel.price || 0.2;
|
||||
let total = unitPrice * tokenLen;
|
||||
total = total > 1 ? total : 1;
|
||||
|
||||
// 插入 Bill 记录
|
||||
if (billId) {
|
||||
concatBill({
|
||||
teamId,
|
||||
tmbId,
|
||||
total,
|
||||
billId,
|
||||
tokens: tokenLen,
|
||||
listIndex: 0
|
||||
});
|
||||
} else {
|
||||
createBill({
|
||||
teamId,
|
||||
tmbId,
|
||||
appName: '索引生成',
|
||||
total,
|
||||
source,
|
||||
list: [
|
||||
{
|
||||
moduleName: '索引生成',
|
||||
amount: total,
|
||||
model: vectorModel.name,
|
||||
tokenLen
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
return { total };
|
||||
};
|
||||
|
||||
export const pushQuestionGuideBill = ({
|
||||
tokens,
|
||||
teamId,
|
||||
tmbId
|
||||
}: {
|
||||
tokens: number;
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
}) => {
|
||||
const qgModel = global.qgModels?.[0] || defaultQGModels[0];
|
||||
const total = qgModel.price * tokens;
|
||||
createBill({
|
||||
teamId,
|
||||
tmbId,
|
||||
appName: '下一步指引',
|
||||
total,
|
||||
source: BillSourceEnum.fastgpt,
|
||||
list: [
|
||||
{
|
||||
moduleName: '下一步指引',
|
||||
amount: total,
|
||||
model: qgModel.name,
|
||||
tokenLen: tokens
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
export function pushAudioSpeechBill({
|
||||
appName = 'wallet.bill.Audio Speech',
|
||||
model,
|
||||
textLength,
|
||||
teamId,
|
||||
tmbId,
|
||||
source = BillSourceEnum.fastgpt
|
||||
}: {
|
||||
appName?: string;
|
||||
model: string;
|
||||
textLength: number;
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
source: `${BillSourceEnum}`;
|
||||
}) {
|
||||
const modelData = getAudioSpeechModel(model);
|
||||
const total = modelData.price * textLength;
|
||||
createBill({
|
||||
teamId,
|
||||
tmbId,
|
||||
appName,
|
||||
total,
|
||||
source,
|
||||
list: [
|
||||
{
|
||||
moduleName: appName,
|
||||
amount: total,
|
||||
model: modelData.name,
|
||||
tokenLen: textLength
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
32
projects/app/src/service/support/wallet/bill/utils.ts
Normal file
32
projects/app/src/service/support/wallet/bill/utils.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ModelTypeEnum, getModelMap } from '@/service/core/ai/model';
|
||||
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||
|
||||
export function authType2BillSource({
|
||||
authType,
|
||||
shareId,
|
||||
source
|
||||
}: {
|
||||
authType?: `${AuthUserTypeEnum}`;
|
||||
shareId?: string;
|
||||
source?: `${BillSourceEnum}`;
|
||||
}) {
|
||||
if (source) return source;
|
||||
if (shareId) return BillSourceEnum.shareLink;
|
||||
if (authType === AuthUserTypeEnum.apikey) return BillSourceEnum.api;
|
||||
return BillSourceEnum.fastgpt;
|
||||
}
|
||||
|
||||
export const countModelPrice = ({
|
||||
model,
|
||||
tokens,
|
||||
type
|
||||
}: {
|
||||
model: string;
|
||||
tokens: number;
|
||||
type: `${ModelTypeEnum}`;
|
||||
}) => {
|
||||
const modelData = getModelMap?.[type]?.(model);
|
||||
if (!modelData) return 0;
|
||||
return modelData.price * tokens;
|
||||
};
|
Reference in New Issue
Block a user