mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-30 02:12:38 +00:00
Add share link hook (#351)
This commit is contained in:
@@ -40,7 +40,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
await connectToDatabase();
|
||||
|
||||
/* user auth */
|
||||
const { userId, user } = await authUser({ req, authBalance: true });
|
||||
const { userId, user } = await authUser({ req, authToken: true, authBalance: true });
|
||||
|
||||
if (!user) {
|
||||
throw new Error('user not found');
|
||||
|
@@ -9,7 +9,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
try {
|
||||
const { name } = req.body as CreateTrainingBillType;
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
const { userId } = await authUser({ req, authToken: true, authApiKey: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
|
@@ -16,7 +16,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
}
|
||||
|
||||
// 凭证校验
|
||||
const { userId } = await authUser({ req });
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await PgClient.delete(PgDatasetTableName, {
|
||||
where: [['user_id', userId], 'AND', ['id', dataId]]
|
||||
|
@@ -21,7 +21,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
await connectToDatabase();
|
||||
|
||||
// 凭证校验
|
||||
const { userId } = await authUser({ req });
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
jsonRes(res, {
|
||||
data: await getVectorAndInsertDataset({
|
||||
|
@@ -36,7 +36,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
await connectToDatabase();
|
||||
|
||||
// 凭证校验
|
||||
const { userId } = await authUser({ req });
|
||||
const { userId } = await authUser({ req, authToken: true, authApiKey: true });
|
||||
|
||||
jsonRes<PushDataResponse>(res, {
|
||||
data: await pushDataToKb({
|
||||
|
@@ -20,7 +20,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
|
||||
// auth user and get kb
|
||||
const [{ userId }, kb] = await Promise.all([
|
||||
authUser({ req }),
|
||||
authUser({ req, authToken: true }),
|
||||
KB.findById(kbId, 'vectorModel')
|
||||
]);
|
||||
|
||||
|
@@ -18,7 +18,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
|
||||
// 凭证校验
|
||||
const [{ userId }, kb] = await Promise.all([
|
||||
authUser({ req }),
|
||||
authUser({ req, authToken: true, authApiKey: true }),
|
||||
KB.findById(kbId, 'vectorModel')
|
||||
]);
|
||||
|
||||
|
@@ -17,7 +17,7 @@ type Response = {
|
||||
|
||||
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
const { userId } = await authUser({ req });
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
let { input, model } = req.query as Props;
|
||||
|
||||
if (!Array.isArray(input)) {
|
||||
|
@@ -34,7 +34,7 @@ import requestIp from 'request-ip';
|
||||
import { replaceVariable } from '@/utils/common/tools/text';
|
||||
import { ModuleDispatchProps } from '@/types/core/modules';
|
||||
import { selectShareResponse } from '@/utils/service/core/chat';
|
||||
import { updateOutLinkUsage } from '@/service/support/outLink';
|
||||
import { pushResult2Remote, updateOutLinkUsage } from '@/service/support/outLink';
|
||||
import { updateApiKeyUsage } from '@/service/support/openapi';
|
||||
|
||||
export type MessageItemType = ChatCompletionRequestMessage & { dataId?: string };
|
||||
@@ -44,6 +44,7 @@ type FastGptWebChatProps = {
|
||||
};
|
||||
type FastGptShareChatProps = {
|
||||
shareId?: string;
|
||||
authToken?: string;
|
||||
};
|
||||
export type Props = CreateChatCompletionRequest &
|
||||
FastGptWebChatProps &
|
||||
@@ -71,6 +72,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
chatId,
|
||||
appId,
|
||||
shareId,
|
||||
authToken,
|
||||
stream = false,
|
||||
detail = false,
|
||||
messages = [],
|
||||
@@ -111,10 +113,15 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
if (shareId) {
|
||||
return authOutLinkChat({
|
||||
shareId,
|
||||
ip: requestIp.getClientIp(req)
|
||||
ip: requestIp.getClientIp(req),
|
||||
authToken,
|
||||
question:
|
||||
(messages[messages.length - 2]?.role === 'user'
|
||||
? messages[messages.length - 2].content
|
||||
: messages[messages.length - 1]?.content) || ''
|
||||
});
|
||||
}
|
||||
return authUser({ req, authBalance: true });
|
||||
return authUser({ req, authToken: true, authApiKey: true, authBalance: true });
|
||||
})();
|
||||
|
||||
if (!user) {
|
||||
@@ -260,11 +267,13 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
response: responseData
|
||||
});
|
||||
|
||||
!!shareId &&
|
||||
if (shareId) {
|
||||
pushResult2Remote({ authToken, shareId, responseData });
|
||||
updateOutLinkUsage({
|
||||
shareId,
|
||||
total
|
||||
});
|
||||
}
|
||||
!!apikey &&
|
||||
updateApiKeyUsage({
|
||||
apikey,
|
||||
|
@@ -16,7 +16,7 @@ export type Response = { history: ChatItemType[] };
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { userId } = await authUser({ req });
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
const { chatId, limit } = req.body as Props;
|
||||
|
||||
jsonRes<Response>(res, {
|
||||
|
@@ -18,7 +18,7 @@ const fetchContent = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
throw new Error('urlList is empty');
|
||||
}
|
||||
|
||||
await authUser({ req });
|
||||
await authUser({ req, authToken: true });
|
||||
|
||||
urlList = urlList.filter((url) => /^(http|https):\/\/[^ "]+$/.test(url));
|
||||
|
||||
|
@@ -14,7 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
throw new Error('fileId is empty');
|
||||
}
|
||||
|
||||
const { userId } = await authUser({ req });
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
const gridFs = new GridFSStorage('dataset', userId);
|
||||
|
||||
|
@@ -16,7 +16,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
throw new Error('fileId is empty');
|
||||
}
|
||||
|
||||
const { userId } = await authUser({ req });
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
// auth file
|
||||
const gridFs = new GridFSStorage('dataset', userId);
|
||||
|
@@ -5,12 +5,14 @@ import type { InitShareChatResponse } from '@/api/response/chat';
|
||||
import { authApp } from '@/service/utils/auth';
|
||||
import { HUMAN_ICON } from '@/constants/chat';
|
||||
import { getChatModelNameList, getSpecialModule } from '@/components/ChatBox/utils';
|
||||
import { authShareChatInit } from '@/service/support/outLink/auth';
|
||||
|
||||
/* init share chat window */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
let { shareId } = req.query as {
|
||||
let { shareId, authToken } = req.query as {
|
||||
shareId: string;
|
||||
authToken?: string;
|
||||
};
|
||||
|
||||
if (!shareId) {
|
||||
@@ -36,7 +38,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
userId: String(shareChat.userId),
|
||||
authOwner: false
|
||||
}),
|
||||
User.findById(shareChat.userId, 'avatar')
|
||||
User.findById(shareChat.userId, 'avatar'),
|
||||
authShareChatInit(authToken, shareChat.limit?.hookUrl)
|
||||
]);
|
||||
|
||||
jsonRes<InitShareChatResponse>(res, {
|
||||
|
@@ -17,7 +17,8 @@ import {
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuList,
|
||||
MenuItem
|
||||
MenuItem,
|
||||
Link
|
||||
} from '@chakra-ui/react';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import MyIcon from '@/components/Icon';
|
||||
@@ -58,7 +59,7 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
} = useQuery(['initShareChatList', appId], () => getShareChatList(appId));
|
||||
|
||||
return (
|
||||
<Box position={'relative'} pt={[3, 5, 8]} px={[5, 8]} minH={'50vh'}>
|
||||
<Box position={'relative'} pt={[3, 5, 8]} px={[2, 8]} minH={'50vh'}>
|
||||
<Flex justifyContent={'space-between'}>
|
||||
<Box fontWeight={'bold'}>
|
||||
免登录窗口
|
||||
@@ -85,7 +86,7 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
</Button>
|
||||
</Flex>
|
||||
<TableContainer mt={3}>
|
||||
<Table variant={'simple'} w={'100%'} overflowX={'auto'}>
|
||||
<Table variant={'simple'} w={'100%'} overflowX={'auto'} fontSize={'sm'}>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>名称</Th>
|
||||
@@ -96,6 +97,7 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
<Th>金额限制(¥)</Th>
|
||||
<Th>IP限流(人/分钟)</Th>
|
||||
<Th>过期时间</Th>
|
||||
<Th>token校验</Th>
|
||||
</>
|
||||
)}
|
||||
<Th>最后使用时间</Th>
|
||||
@@ -113,12 +115,13 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
<Td>
|
||||
{item.limit && item.limit.credit > -1 ? `${item.limit.credit}元` : '无限制'}
|
||||
</Td>
|
||||
<Td>{item.limit?.QPM || '-'}</Td>
|
||||
<Td>{item?.limit?.QPM || '-'}</Td>
|
||||
<Td>
|
||||
{item.limit?.expiredTime
|
||||
{item?.limit?.expiredTime
|
||||
? dayjs(item.limit?.expiredTime).format('YYYY/MM/DD\nHH:mm')
|
||||
: '-'}
|
||||
</Td>
|
||||
<Th>{item?.limit?.hookUrl ? '✔' : '✖'}</Th>
|
||||
</>
|
||||
)}
|
||||
<Td>{item.lastTime ? formatTimeToChatTime(item.lastTime) : '未使用'}</Td>
|
||||
@@ -267,7 +270,6 @@ function EditLinkModal({
|
||||
});
|
||||
const { mutate: onclickUpdate, isLoading: updating } = useRequest({
|
||||
mutationFn: (e: OutLinkEditType) => {
|
||||
console.log(e);
|
||||
return putShareChat(e);
|
||||
},
|
||||
errorToast: '更新链接异常',
|
||||
@@ -338,6 +340,26 @@ function EditLinkModal({
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'}>
|
||||
{t('outlink.token auth')}
|
||||
<MyTooltip label={t('outlink.token auth Tips') || ''}>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
<Input
|
||||
placeholder={t('outlink.token auth Tips') || ''}
|
||||
{...register('limit.hookUrl')}
|
||||
/>
|
||||
</Flex>
|
||||
<Link
|
||||
href="https://doc.fastgpt.run/docs/development/openapi/#分享链接中增加额外-query"
|
||||
target={'_blank'}
|
||||
fontSize={'sm'}
|
||||
color={'myGray.500'}
|
||||
>
|
||||
{t('outlink.token auth use cases')}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
@@ -21,11 +21,20 @@ import ChatHeader from './components/ChatHeader';
|
||||
import ChatHistorySlider from './components/ChatHistorySlider';
|
||||
import { serviceSideProps } from '@/utils/web/i18n';
|
||||
|
||||
const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
const OutLink = ({
|
||||
shareId,
|
||||
chatId,
|
||||
authToken
|
||||
}: {
|
||||
shareId: string;
|
||||
chatId: string;
|
||||
authToken?: string;
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const { isOpen: isOpenSlider, onClose: onCloseSlider, onOpen: onOpenSlider } = useDisclosure();
|
||||
const { isPc } = useGlobalStore();
|
||||
const forbidRefresh = useRef(false);
|
||||
|
||||
const ChatBoxRef = useRef<ComponentRef>(null);
|
||||
|
||||
@@ -53,7 +62,8 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
messages: prompts,
|
||||
variables,
|
||||
shareId,
|
||||
chatId: completionChatId
|
||||
chatId: completionChatId,
|
||||
authToken
|
||||
},
|
||||
onMessage: generatingMessage,
|
||||
abortSignal: controller
|
||||
@@ -75,10 +85,12 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
});
|
||||
|
||||
if (completionChatId !== chatId && controller.signal.reason !== 'leave') {
|
||||
forbidRefresh.current = true;
|
||||
router.replace({
|
||||
query: {
|
||||
shareId,
|
||||
chatId: completionChatId
|
||||
chatId: completionChatId,
|
||||
authToken
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -96,11 +108,11 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
|
||||
return { responseText, responseData };
|
||||
},
|
||||
[chatId, router, saveChatResponse, shareId]
|
||||
[authToken, chatId, router, saveChatResponse, shareId]
|
||||
);
|
||||
|
||||
const loadAppInfo = useCallback(
|
||||
async (shareId: string, chatId: string) => {
|
||||
async (shareId: string, chatId: string, authToken?: string) => {
|
||||
if (!shareId) return null;
|
||||
const history = shareChatHistory.find((item) => item.chatId === chatId) || defaultHistory;
|
||||
|
||||
@@ -111,7 +123,8 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
const chatData = await (async () => {
|
||||
if (shareChatData.app.name === '') {
|
||||
return initShareChatInfo({
|
||||
shareId
|
||||
shareId,
|
||||
authToken
|
||||
});
|
||||
}
|
||||
return shareChatData;
|
||||
@@ -142,8 +155,12 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
[delManyShareChatHistoryByShareId, setShareChatData, shareChatData, shareChatHistory, toast]
|
||||
);
|
||||
|
||||
useQuery(['init', shareId, chatId], () => {
|
||||
return loadAppInfo(shareId, chatId);
|
||||
useQuery(['init', shareId, chatId, authToken], () => {
|
||||
if (forbidRefresh.current) {
|
||||
forbidRefresh.current = false;
|
||||
return null;
|
||||
}
|
||||
return loadAppInfo(shareId, chatId, authToken);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -185,7 +202,8 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
router.replace({
|
||||
query: {
|
||||
chatId: chatId || '',
|
||||
shareId
|
||||
shareId,
|
||||
authToken
|
||||
}
|
||||
});
|
||||
if (!isPc) {
|
||||
@@ -197,7 +215,8 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
delManyShareChatHistoryByShareId(shareId);
|
||||
router.replace({
|
||||
query: {
|
||||
shareId
|
||||
shareId,
|
||||
authToken
|
||||
}
|
||||
});
|
||||
}}
|
||||
@@ -222,6 +241,7 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
{/* chat box */}
|
||||
<Box flex={1}>
|
||||
<ChatBox
|
||||
active={!!shareChatData.app.name}
|
||||
ref={ChatBoxRef}
|
||||
appAvatar={shareChatData.app.avatar}
|
||||
userAvatar={shareChatData.userAvatar}
|
||||
@@ -252,9 +272,10 @@ const OutLink = ({ shareId, chatId }: { shareId: string; chatId: string }) => {
|
||||
export async function getServerSideProps(context: any) {
|
||||
const shareId = context?.query?.shareId || '';
|
||||
const chatId = context?.query?.chatId || '';
|
||||
const authToken = context?.query?.authToken || '';
|
||||
|
||||
return {
|
||||
props: { shareId, chatId, ...(await serviceSideProps(context)) }
|
||||
props: { shareId, chatId, authToken, ...(await serviceSideProps(context)) }
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user