mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-21 03:35:36 +00:00
Feat: prelogin (#4773)
* add prelogin api (#4762) * add prelogin api * move type.d.ts * perf: prelogin code * doc * fix: ts --------- Co-authored-by: dreamer6680 <1468683855@qq.com>
This commit is contained in:
@@ -15,6 +15,7 @@ weight: 792
|
||||
3. qwen3 模型预设
|
||||
4. 语雀知识库支持设置根目录。
|
||||
5. 可配置密码过期时间,过期后下次登录会强制要求修改密码。
|
||||
6. 密码登录增加 preLogin 临时密钥校验。
|
||||
|
||||
## ⚙️ 优化
|
||||
|
||||
|
1
packages/global/support/user/api.d.ts
vendored
1
packages/global/support/user/api.d.ts
vendored
@@ -9,6 +9,7 @@ import type { TeamMemberItemType } from './team/type';
|
||||
export type PostLoginProps = {
|
||||
username: string;
|
||||
password: string;
|
||||
code: string;
|
||||
};
|
||||
|
||||
export type OauthLoginProps = {
|
||||
|
@@ -3,7 +3,8 @@ export enum UserAuthTypeEnum {
|
||||
findPassword = 'findPassword',
|
||||
wxLogin = 'wxLogin',
|
||||
bindNotification = 'bindNotification',
|
||||
captcha = 'captcha'
|
||||
captcha = 'captcha',
|
||||
login = 'login'
|
||||
}
|
||||
|
||||
export const userAuthTypeMap = {
|
||||
@@ -11,5 +12,6 @@ export const userAuthTypeMap = {
|
||||
[UserAuthTypeEnum.findPassword]: 'findPassword',
|
||||
[UserAuthTypeEnum.wxLogin]: 'wxLogin',
|
||||
[UserAuthTypeEnum.bindNotification]: 'bindNotification',
|
||||
[UserAuthTypeEnum.captcha]: 'captcha'
|
||||
[UserAuthTypeEnum.captcha]: 'captcha',
|
||||
[UserAuthTypeEnum.login]: 'login'
|
||||
};
|
||||
|
10
packages/global/support/user/auth/type.d.ts
vendored
Normal file
10
packages/global/support/user/auth/type.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { UserAuthTypeEnum } from '@fastgpt/global/support/user/auth/constants';
|
||||
|
||||
export type UserAuthSchemaType = {
|
||||
key: string;
|
||||
type: `${UserAuthTypeEnum}`;
|
||||
code?: string;
|
||||
openid?: string;
|
||||
createTime: Date;
|
||||
expiredTime: Date;
|
||||
};
|
63
packages/service/support/user/auth/controller.ts
Normal file
63
packages/service/support/user/auth/controller.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { UserAuthTypeEnum } from '@fastgpt/global/support/user/auth/constants';
|
||||
import { MongoUserAuth } from './schema';
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
|
||||
|
||||
export const addAuthCode = async ({
|
||||
key,
|
||||
code,
|
||||
openid,
|
||||
type,
|
||||
expiredTime
|
||||
}: {
|
||||
key: string;
|
||||
code?: string;
|
||||
openid?: string;
|
||||
type: `${UserAuthTypeEnum}`;
|
||||
expiredTime?: Date;
|
||||
}) => {
|
||||
return MongoUserAuth.updateOne(
|
||||
{
|
||||
key,
|
||||
type
|
||||
},
|
||||
{
|
||||
code,
|
||||
openid,
|
||||
expiredTime
|
||||
},
|
||||
{
|
||||
upsert: true
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const authCode = async ({
|
||||
key,
|
||||
type,
|
||||
code
|
||||
}: {
|
||||
key: string;
|
||||
type: `${UserAuthTypeEnum}`;
|
||||
code: string;
|
||||
}) => {
|
||||
return mongoSessionRun(async (session) => {
|
||||
const result = await MongoUserAuth.findOne(
|
||||
{
|
||||
key,
|
||||
type,
|
||||
code: { $regex: new RegExp(`^${code}$`, 'i') }
|
||||
},
|
||||
undefined,
|
||||
{ session }
|
||||
);
|
||||
|
||||
if (!result) {
|
||||
return Promise.reject(i18nT('common:error.code_error'));
|
||||
}
|
||||
|
||||
await result.deleteOne({ session });
|
||||
|
||||
return 'SUCCESS';
|
||||
});
|
||||
};
|
41
packages/service/support/user/auth/schema.ts
Normal file
41
packages/service/support/user/auth/schema.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { connectionMongo, getMongoModel } from '../../../common/mongo';
|
||||
const { Schema } = connectionMongo;
|
||||
import type { UserAuthSchemaType } from '@fastgpt/global/support/user/auth/type';
|
||||
import { userAuthTypeMap } from '@fastgpt/global/support/user/auth/constants';
|
||||
import { addMinutes } from 'date-fns';
|
||||
|
||||
const UserAuthSchema = new Schema({
|
||||
key: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
code: {
|
||||
// auth code
|
||||
type: String,
|
||||
length: 6
|
||||
},
|
||||
// wx openid
|
||||
openid: String,
|
||||
type: {
|
||||
type: String,
|
||||
enum: Object.keys(userAuthTypeMap),
|
||||
required: true
|
||||
},
|
||||
createTime: {
|
||||
type: Date,
|
||||
default: () => new Date()
|
||||
},
|
||||
expiredTime: {
|
||||
type: Date,
|
||||
default: () => addMinutes(new Date(), 5)
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
UserAuthSchema.index({ key: 1, type: 1 });
|
||||
UserAuthSchema.index({ expiredTime: 1 }, { expireAfterSeconds: 0 });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
export const MongoUserAuth = getMongoModel<UserAuthSchemaType>('auth_codes', UserAuthSchema);
|
@@ -2,7 +2,7 @@ import React, { type Dispatch } from 'react';
|
||||
import { FormControl, Flex, Input, Button, Box, Link } from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { LoginPageTypeEnum } from '@/web/support/user/login/constants';
|
||||
import { postLogin } from '@/web/support/user/api';
|
||||
import { postLogin, getPreLogin } from '@/web/support/user/api';
|
||||
import type { ResLogin } from '@/global/support/api/userRes';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
@@ -33,10 +33,12 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
|
||||
const { runAsync: onclickLogin, loading: requesting } = useRequest2(
|
||||
async ({ username, password }: LoginFormType) => {
|
||||
const { code } = await getPreLogin(username);
|
||||
loginSuccess(
|
||||
await postLogin({
|
||||
username,
|
||||
password
|
||||
password,
|
||||
code
|
||||
})
|
||||
);
|
||||
toast({
|
||||
|
@@ -11,14 +11,23 @@ import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
|
||||
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
|
||||
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
|
||||
import { UserAuthTypeEnum } from '@fastgpt/global/support/user/auth/constants';
|
||||
import { authCode } from '@fastgpt/service/support/user/auth/controller';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { username, password } = req.body as PostLoginProps;
|
||||
const { username, password, code } = req.body as PostLoginProps;
|
||||
|
||||
if (!username || !password) {
|
||||
if (!username || !password || !code) {
|
||||
return Promise.reject(CommonErrEnum.invalidParams);
|
||||
}
|
||||
|
||||
// Auth prelogin code
|
||||
await authCode({
|
||||
key: username,
|
||||
code,
|
||||
type: UserAuthTypeEnum.login
|
||||
});
|
||||
|
||||
// 检测用户是否存在
|
||||
const authCert = await MongoUser.findOne(
|
||||
{
|
||||
|
40
projects/app/src/pages/api/support/user/account/preLogin.ts
Normal file
40
projects/app/src/pages/api/support/user/account/preLogin.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { UserAuthTypeEnum } from '@fastgpt/global/support/user/auth/constants';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { addSeconds } from 'date-fns';
|
||||
import { addAuthCode } from '@fastgpt/service/support/user/auth/controller';
|
||||
|
||||
export type preLoginQuery = {
|
||||
username: string;
|
||||
};
|
||||
|
||||
export type preLoginBody = {};
|
||||
|
||||
export type preLoginResponse = { code: string };
|
||||
|
||||
async function handler(
|
||||
req: ApiRequestProps<preLoginBody, preLoginQuery>,
|
||||
res: ApiResponseType<any>
|
||||
): Promise<preLoginResponse> {
|
||||
const { username } = req.query;
|
||||
|
||||
if (!username) {
|
||||
return Promise.reject('username is required');
|
||||
}
|
||||
|
||||
const code = getNanoid(6);
|
||||
|
||||
await addAuthCode({
|
||||
type: UserAuthTypeEnum.login,
|
||||
key: username,
|
||||
code,
|
||||
expiredTime: addSeconds(new Date(), 30)
|
||||
});
|
||||
|
||||
return {
|
||||
code
|
||||
};
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
@@ -14,6 +14,7 @@ import type {
|
||||
AccountRegisterBody,
|
||||
GetWXLoginQRResponse
|
||||
} from '@fastgpt/global/support/user/login/api.d';
|
||||
import type { preLoginResponse } from '@/pages/api/support/user/account/preLogin';
|
||||
|
||||
export const sendAuthCode = (data: {
|
||||
username: string;
|
||||
@@ -104,6 +105,9 @@ export const getCaptchaPic = (username: string) =>
|
||||
captchaImage: string;
|
||||
}>('/proApi/support/user/account/captcha/getImgCaptcha', { username });
|
||||
|
||||
export const getPreLogin = (username: string) =>
|
||||
GET<preLoginResponse>('/support/user/account/preLogin', { username });
|
||||
|
||||
export const postSyncMembers = () => POST('/proApi/support/user/sync');
|
||||
|
||||
export const GetSearchUserGroupOrg = (
|
||||
|
Reference in New Issue
Block a user