mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-21 11:43:56 +00:00
feat: login limit (#3369)
* feat: login limit * feat: env template * fix: ts
This commit is contained in:
@@ -72,7 +72,7 @@ export const ERROR_RESPONSE: Record<
|
||||
[ERROR_ENUM.tooManyRequest]: {
|
||||
code: 429,
|
||||
statusText: ERROR_ENUM.tooManyRequest,
|
||||
message: 'Too many request',
|
||||
message: i18nT('common:error.too_many_request'),
|
||||
data: null
|
||||
},
|
||||
[ERROR_ENUM.insufficientQuota]: {
|
||||
|
@@ -24,7 +24,7 @@ export async function getTmpData<T extends TmpDataEnum>({
|
||||
}).lean()) as TmpDataSchema<TmpDataType<T>> | null;
|
||||
}
|
||||
|
||||
export async function setTmpData<T extends TmpDataEnum>({
|
||||
export function setTmpData<T extends TmpDataEnum>({
|
||||
type,
|
||||
metadata,
|
||||
data
|
||||
@@ -33,7 +33,7 @@ export async function setTmpData<T extends TmpDataEnum>({
|
||||
metadata: TmpDataMetadata<T>;
|
||||
data: TmpDataType<T>;
|
||||
}) {
|
||||
return await MongoTmpData.updateOne(
|
||||
return MongoTmpData.updateOne(
|
||||
{
|
||||
dataId: getDataId(type, metadata)
|
||||
},
|
||||
@@ -43,7 +43,8 @@ export async function setTmpData<T extends TmpDataEnum>({
|
||||
expireAt: addMilliseconds(Date.now(), TmpDataExpireTime[type])
|
||||
},
|
||||
{
|
||||
upsert: true
|
||||
upsert: true,
|
||||
new: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@@ -874,6 +874,7 @@
|
||||
"error.fileNotFound": "File not found~",
|
||||
"error.inheritPermissionError": "Inherit permission Error",
|
||||
"error.missingParams": "Insufficient parameters",
|
||||
"error.too_many_request": "Too many request",
|
||||
"error.upload_file_error_filename": "{{name}} Upload Failed",
|
||||
"error.username_empty": "Account cannot be empty",
|
||||
"extraction_results": "Extraction Results",
|
||||
|
@@ -873,6 +873,7 @@
|
||||
"error.fileNotFound": "文件找不到了~",
|
||||
"error.inheritPermissionError": "权限继承错误",
|
||||
"error.missingParams": "参数缺失",
|
||||
"error.too_many_request": "请求太频繁了,请稍后重试",
|
||||
"error.upload_file_error_filename": "{{name}} 上传失败",
|
||||
"error.username_empty": "账号不能为空",
|
||||
"extraction_results": "提取结果",
|
||||
@@ -1179,7 +1180,6 @@
|
||||
"user.password_message": "密码最少 4 位最多 60 位",
|
||||
"user.team.Balance": "团队余额",
|
||||
"user.team.Check Team": "切换",
|
||||
|
||||
"user.team.Invite Member": "邀请成员",
|
||||
"user.team.Invite Member Tips": "对方可查阅或使用团队内的其他资源",
|
||||
"user.team.Leave Team": "离开团队",
|
||||
@@ -1192,13 +1192,10 @@
|
||||
"user.team.Processing invitations Tips": "你有 {{amount}} 个需要处理的团队邀请",
|
||||
"user.team.Remove Member Confirm Tip": "确认将 {{username}} 移出团队?",
|
||||
"user.team.Select Team": "团队选择",
|
||||
|
||||
"user.team.Switch Team Failed": "切换团队异常",
|
||||
"user.team.Tags Async": "保存",
|
||||
|
||||
"user.team.Team Tags Async": "标签同步",
|
||||
"user.team.Team Tags Async Success": "链接报错成功,标签信息更新",
|
||||
|
||||
"user.team.invite.Accept Confirm": "确认加入该团队?",
|
||||
"user.team.invite.Accepted": "已加入团队",
|
||||
"user.team.invite.Deal Width Footer Tip": "处理完会自动关闭噢~",
|
||||
|
@@ -873,6 +873,7 @@
|
||||
"error.fileNotFound": "找不到檔案",
|
||||
"error.inheritPermissionError": "繼承權限錯誤",
|
||||
"error.missingParams": "參數不足",
|
||||
"error.too_many_request": "請求太頻繁了,請稍後重試",
|
||||
"error.upload_file_error_filename": "{{name}} 上傳失敗",
|
||||
"error.username_empty": "帳號不能為空",
|
||||
"extraction_results": "提取結果",
|
||||
|
@@ -43,6 +43,8 @@ LOG_LEVEL=debug
|
||||
STORE_LOG_LEVEL=warn
|
||||
|
||||
# 安全配置
|
||||
# 启动 IP 限流(true),部分接口增加了 ip 限流策略,防止非正常请求操作。
|
||||
USE_IP_LIMIT=false
|
||||
# 工作流最大运行次数,避免极端的死循环情况
|
||||
WORKFLOW_MAX_RUN_TIMES=500
|
||||
# 循环最大运行次数,避免极端的死循环情况
|
||||
|
@@ -99,4 +99,4 @@ async function handler(req: NextApiRequest) {
|
||||
};
|
||||
}
|
||||
|
||||
export default NextAPI(useReqFrequencyLimit(1, 2), handler);
|
||||
export default NextAPI(useReqFrequencyLimit(1, 15), handler);
|
||||
|
@@ -1,71 +1,63 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { MongoUser } from '@fastgpt/service/support/user/schema';
|
||||
import { createJWT, setCookie } from '@fastgpt/service/support/permission/controller';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { getUserDetail } from '@fastgpt/service/support/user/controller';
|
||||
import type { PostLoginProps } from '@fastgpt/global/support/user/api.d';
|
||||
import { UserStatusEnum } from '@fastgpt/global/support/user/constant';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { useReqFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { username, password } = req.body as PostLoginProps;
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { username, password } = req.body as PostLoginProps;
|
||||
|
||||
if (!username || !password) {
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
// 检测用户是否存在
|
||||
const authCert = await MongoUser.findOne(
|
||||
{
|
||||
username
|
||||
},
|
||||
'status'
|
||||
);
|
||||
if (!authCert) {
|
||||
throw new Error('用户未注册');
|
||||
}
|
||||
|
||||
if (authCert.status === UserStatusEnum.forbidden) {
|
||||
throw new Error('账号已停用,无法登录');
|
||||
}
|
||||
|
||||
const user = await MongoUser.findOne({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new Error('密码错误');
|
||||
}
|
||||
|
||||
const userDetail = await getUserDetail({
|
||||
tmbId: user?.lastLoginTmbId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
MongoUser.findByIdAndUpdate(user._id, {
|
||||
lastLoginTmbId: userDetail.team.tmbId
|
||||
});
|
||||
|
||||
const token = createJWT({
|
||||
...userDetail,
|
||||
isRoot: username === 'root'
|
||||
});
|
||||
|
||||
setCookie(res, token);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
user: userDetail,
|
||||
token
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
if (!username || !password) {
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
// 检测用户是否存在
|
||||
const authCert = await MongoUser.findOne(
|
||||
{
|
||||
username
|
||||
},
|
||||
'status'
|
||||
);
|
||||
if (!authCert) {
|
||||
throw new Error('用户未注册');
|
||||
}
|
||||
|
||||
if (authCert.status === UserStatusEnum.forbidden) {
|
||||
throw new Error('账号已停用,无法登录');
|
||||
}
|
||||
|
||||
const user = await MongoUser.findOne({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new Error('密码错误');
|
||||
}
|
||||
|
||||
const userDetail = await getUserDetail({
|
||||
tmbId: user?.lastLoginTmbId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
MongoUser.findByIdAndUpdate(user._id, {
|
||||
lastLoginTmbId: userDetail.team.tmbId
|
||||
});
|
||||
|
||||
const token = createJWT({
|
||||
...userDetail,
|
||||
isRoot: username === 'root'
|
||||
});
|
||||
|
||||
setCookie(res, token);
|
||||
|
||||
return {
|
||||
user: userDetail,
|
||||
token
|
||||
};
|
||||
}
|
||||
|
||||
export default NextAPI(useReqFrequencyLimit(120, 10), handler);
|
||||
|
@@ -89,7 +89,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
removeFilesByPaths(filePaths);
|
||||
}
|
||||
|
||||
export default NextAPI(useReqFrequencyLimit(1, 2), handler);
|
||||
export default NextAPI(useReqFrequencyLimit(1, 1), handler);
|
||||
|
||||
export const config = {
|
||||
api: {
|
||||
|
Reference in New Issue
Block a user