fix: login secret (#6635)

* fix: login secret

* lock

* env template

* fix: ts

* fix: ts

* fix: ts
This commit is contained in:
Archer
2026-03-25 14:45:38 +08:00
committed by GitHub
parent e48a037f2d
commit bd966d479f
54 changed files with 2061 additions and 500 deletions
@@ -0,0 +1,10 @@
import type { OpenAPIPath } from '../../../type';
import { LoginPath } from './login';
import { RegisterPath } from './register';
import { PasswordPath } from './password';
export const UserAccountPath: OpenAPIPath = {
...LoginPath,
...RegisterPath,
...PasswordPath
};
@@ -0,0 +1,110 @@
import { z } from 'zod';
import { OAuthEnum } from '../../../../../support/user/constant';
import { TrackRegisterParamsSchema } from '../../../../../support/marketing/type';
import { LanguageSchema } from '../../../../../common/i18n/type';
export const LoginSuccessResponseSchema = z.object({
user: z.any().meta({
description: '用户详情'
}),
token: z.string().meta({
example: 'eyJhbGciOiJIUzI1NiIs...',
description: '登录令牌'
})
});
export type LoginSuccessResponseType = z.infer<typeof LoginSuccessResponseSchema>;
// ===== Pre login - get login verification code =====
export const PreLoginQuerySchema = z.object({
username: z.string().meta({
example: 'admin',
description: '用户名'
})
});
export type PreLoginQueryType = z.infer<typeof PreLoginQuerySchema>;
export const PreLoginResponseSchema = z
.object({
code: z.string().meta({
example: 'a1b2c3',
description: '预登录验证码'
})
})
.meta({
example: {
code: 'a1b2c3'
}
});
export type PreLoginResponseType = z.infer<typeof PreLoginResponseSchema>;
// ===== Login by password =====
export const LoginByPasswordBodySchema = z
.object({
username: z.string().meta({
example: 'admin',
description: '用户名'
}),
password: z.string().meta({
example: 'hashed_password',
description: '密码'
}),
code: z.string().meta({
example: '123456',
description: '预登录验证码'
}),
language: LanguageSchema.optional().default('zh-CN').meta({
example: 'zh-CN',
description: '用户语言偏好'
})
})
.meta({
example: {
username: 'admin',
password: 'hashed_password',
code: '123456',
language: 'zh-CN'
}
});
export type LoginByPasswordBodyType = z.infer<typeof LoginByPasswordBodySchema>;
/* ===== Wecom Login ===== */
export const WecomGetRedirectURLBodySchema = z.object({
redirectUri: z.string(),
state: z.string(),
isWecomWorkTerminal: z.boolean()
});
export const WecomGetRedirectURLResponseSchema = z.string();
export type WecomGetRedirectURLBodyType = z.infer<typeof WecomGetRedirectURLBodySchema>;
export type WecomGetRedirectURLResponseType = z.infer<typeof WecomGetRedirectURLResponseSchema>;
// ===== OAuth Login =====
export const OauthLoginBodySchema = TrackRegisterParamsSchema.extend({
type: z.enum(OAuthEnum).meta({ description: 'OAuth 登录类型' }),
callbackUrl: z.string().meta({ description: '回调 URL' }),
props: z.record(z.string(), z.string()).meta({ description: '附加属性' }),
language: LanguageSchema.optional().meta({ description: '语言' })
});
export type OauthLoginBodyType = z.infer<typeof OauthLoginBodySchema>;
// ===== Fast Login =====
export const FastLoginBodySchema = z.object({
token: z.string().meta({ description: 'Token' }),
code: z.string().meta({ description: 'Code' })
});
export type FastLoginBodyType = z.infer<typeof FastLoginBodySchema>;
// ===== WeChat Login Result =====
export const WxLoginBodySchema = z.object({
inviterId: z.string().optional().meta({ description: '邀请人 ID' }),
code: z.string().meta({ description: '微信登录 Code' }),
bd_vid: z.string().optional(),
msclkid: z.string().optional(),
fastgpt_sem: z.string().optional(),
sourceDomain: z.string().optional()
});
export type WxLoginBodyType = z.infer<typeof WxLoginBodySchema>;
export const GetWXLoginQRResponseSchema = z.object({
code: z.string().meta({ description: '微信登录 Code' }),
codeUrl: z.string().meta({ description: '微信登录二维码 URL' })
});
export type GetWXLoginQRResponseType = z.infer<typeof GetWXLoginQRResponseSchema>;
@@ -0,0 +1,178 @@
import type { OpenAPIPath } from '../../../../type';
import { TagsMap } from '../../../../tag';
import {
LoginByPasswordBodySchema,
PreLoginQuerySchema,
PreLoginResponseSchema,
OauthLoginBodySchema,
FastLoginBodySchema,
WxLoginBodySchema,
GetWXLoginQRResponseSchema,
LoginSuccessResponseSchema
} from './api';
import { UserSchema } from '../../../../../support/user/type';
export const LoginPath: OpenAPIPath = {
'/support/user/account/tokenLogin': {
get: {
summary: 'Token 登录',
description: '通过已有的登录令牌获取用户信息',
tags: [TagsMap.userLogin],
responses: {
200: {
description: '成功获取用户信息',
content: {
'application/json': {
schema: UserSchema
}
}
}
}
}
},
'/support/user/account/preLogin': {
get: {
summary: '预登录获取验证码',
description: '通过用户名获取预登录验证码,用于密码登录时的验证',
tags: [TagsMap.userLogin],
requestParams: {
query: PreLoginQuerySchema
},
responses: {
200: {
description: '成功获取预登录验证码',
content: {
'application/json': {
schema: PreLoginResponseSchema
}
}
}
}
}
},
'/support/user/account/loginByPassword': {
post: {
summary: '用户密码登录',
description: '通过用户名和密码进行登录,需要先获取预登录验证码',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: LoginByPasswordBodySchema
}
}
},
responses: {
200: {
description: '登录成功,返回用户信息和令牌',
content: {
'application/json': {
schema: LoginSuccessResponseSchema
}
}
}
}
}
},
'/proApi/support/user/account/login/oauth': {
post: {
summary: 'OAuth 登录',
description: '使用第三方 OAuth 授权登录',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: OauthLoginBodySchema
}
}
},
responses: {
200: {
description: '登录成功',
content: {
'application/json': {
schema: LoginSuccessResponseSchema
}
}
}
}
}
},
'/proApi/support/user/account/login/fastLogin': {
post: {
summary: '快捷登录',
description: '使用 Token 和 Code 进行快捷登录',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: FastLoginBodySchema
}
}
},
responses: {
200: {
description: '登录成功',
content: {
'application/json': {
schema: LoginSuccessResponseSchema
}
}
}
}
}
},
'/proApi/support/user/account/login/wx/getQR': {
get: {
summary: '获取微信登录二维码',
description: '获取微信登录二维码',
tags: [TagsMap.userLogin],
responses: {
200: {
description: '获取微信登录二维码成功',
content: {
'application/json': {
schema: GetWXLoginQRResponseSchema
}
}
}
}
}
},
'/proApi/support/user/account/login/wx/getResult': {
post: {
summary: '获取微信登录结果',
description: '提交微信登录 Code 以获取登录结果',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: WxLoginBodySchema
}
}
},
responses: {
200: {
description: '登录成功',
content: {
'application/json': {
schema: LoginSuccessResponseSchema
}
}
}
}
}
},
'/support/user/account/loginout': {
get: {
summary: '退出登录',
description: '退出当前用户的所有会话并清除登录凭证',
tags: [TagsMap.userLogin],
responses: {
200: {
description: '退出登录成功'
}
}
}
}
};
@@ -1,12 +0,0 @@
import { z } from 'zod';
export const WecomGetRedirectURLBodySchema = z.object({
redirectUri: z.string(),
state: z.string(),
isWecomWorkTerminal: z.boolean()
});
export const WecomGetRedirectURLResponseSchema = z.string();
export type WecomGetRedirectURLBodyType = z.infer<typeof WecomGetRedirectURLBodySchema>;
export type WecomGetRedirectURLResponseType = z.infer<typeof WecomGetRedirectURLResponseSchema>;
@@ -0,0 +1,62 @@
import { z } from 'zod';
// ===== Update password by old password =====
export const UpdatePasswordByOldBodySchema = z
.object({
oldPsw: z.string().trim().min(1).meta({
example: 'hashed_old_password',
description: '旧密码(已加密)'
}),
newPsw: z.string().trim().min(1).meta({
example: 'hashed_new_password',
description: '新密码(已加密)'
})
})
.meta({
example: {
oldPsw: 'hashed_old_password',
newPsw: 'hashed_new_password'
}
});
export type UpdatePasswordByOldBodyType = z.infer<typeof UpdatePasswordByOldBodySchema>;
export const UpdatePasswordByOldResponseSchema = z.any().meta({
description: '用户信息'
});
export type UpdatePasswordByOldResponseType = z.infer<typeof UpdatePasswordByOldResponseSchema>;
// ===== Check password expired =====
export const CheckPswExpiredResponseSchema = z.boolean().meta({
example: false,
description: '密码是否已过期'
});
export type CheckPswExpiredResponseType = z.infer<typeof CheckPswExpiredResponseSchema>;
// ===== Reset expired password =====
export const ResetExpiredPswBodySchema = z
.object({
newPsw: z.string().trim().min(1).meta({
example: 'hashed_new_password',
description: '新密码(已加密)'
})
})
.meta({
example: {
newPsw: 'hashed_new_password'
}
});
export type ResetExpiredPswBodyType = z.infer<typeof ResetExpiredPswBodySchema>;
export const ResetExpiredPswResponseSchema = z.object({}).meta({
description: '重置成功'
});
export type ResetExpiredPswResponseType = z.infer<typeof ResetExpiredPswResponseSchema>;
// ===== Find Password (update by code) =====
export const UpdatePasswordByCodeBodySchema = z.object({
username: z.string().trim().min(1).meta({ description: '用户名' }),
code: z.string().meta({ description: '验证码' }),
password: z.string().trim().min(1).meta({ description: '新密码' }),
tmbId: z.string().optional().meta({ description: '团队成员 ID(可选)' })
});
export type UpdatePasswordByCodeBodyType = z.infer<typeof UpdatePasswordByCodeBodySchema>;
@@ -0,0 +1,102 @@
import type { OpenAPIPath } from '../../../../type';
import { TagsMap } from '../../../../tag';
import {
UpdatePasswordByOldBodySchema,
UpdatePasswordByOldResponseSchema,
CheckPswExpiredResponseSchema,
ResetExpiredPswBodySchema,
ResetExpiredPswResponseSchema,
UpdatePasswordByCodeBodySchema
} from './api';
export const PasswordPath: OpenAPIPath = {
'/support/user/account/updatePasswordByOld': {
post: {
summary: '通过旧密码修改密码',
description: '使用旧密码验证后修改为新密码,修改成功后其他会话将被注销',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: UpdatePasswordByOldBodySchema
}
}
},
responses: {
200: {
description: '密码修改成功',
content: {
'application/json': {
schema: UpdatePasswordByOldResponseSchema
}
}
}
}
}
},
'/support/user/account/checkPswExpired': {
get: {
summary: '检查密码是否过期',
description: '检查当前用户的密码是否已过期,需要强制修改',
tags: [TagsMap.userLogin],
responses: {
200: {
description: '返回密码是否过期',
content: {
'application/json': {
schema: CheckPswExpiredResponseSchema
}
}
}
}
}
},
'/support/user/account/resetExpiredPsw': {
post: {
summary: '重置过期密码',
description: '当密码过期时,使用此接口重置密码,重置后其他会话将被注销',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: ResetExpiredPswBodySchema
}
}
},
responses: {
200: {
description: '密码重置成功',
content: {
'application/json': {
schema: ResetExpiredPswResponseSchema
}
}
}
}
}
},
'/support/user/account/password/updateByCode': {
post: {
summary: '通过验证码找回/修改密码',
description: '通过邮箱/手机验证码找回或修改密码',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: UpdatePasswordByCodeBodySchema
}
}
},
responses: {
200: {
description: '修改成功',
content: {
'application/json': {
schema: {}
}
}
}
}
}
}
};
@@ -0,0 +1,13 @@
import { z } from 'zod';
import { TrackRegisterParamsSchema } from '../../../../../support/marketing/type';
import { LanguageSchema } from '../../../../../common/i18n/type';
// ===== Register by email or phone =====
export const AccountRegisterBodySchema = TrackRegisterParamsSchema.extend({
username: z.string().meta({ description: '用户名(邮箱或手机号)' }),
code: z.string().meta({ description: '验证码' }),
password: z.string().meta({ description: '密码(已加密)' }),
language: LanguageSchema.optional().meta({ description: '语言' })
});
export type AccountRegisterBodyType = z.infer<typeof AccountRegisterBodySchema>;
@@ -0,0 +1,30 @@
import type { OpenAPIPath } from '../../../../type';
import { TagsMap } from '../../../../tag';
import { AccountRegisterBodySchema } from './api';
export const RegisterPath: OpenAPIPath = {
'/support/user/account/register/emailAndPhone': {
post: {
summary: '邮箱/手机号注册',
description: '使用邮箱或手机号验证码注册新账号',
tags: [TagsMap.userLogin],
requestBody: {
content: {
'application/json': {
schema: AccountRegisterBodySchema
}
}
},
responses: {
200: {
description: '注册成功',
content: {
'application/json': {
schema: {}
}
}
}
}
}
}
};
@@ -1,6 +1,8 @@
import { UserInformPath } from './inform';
import type { OpenAPIPath } from '../../type';
import { UserAccountPath } from './account';
export const UserPath: OpenAPIPath = {
...UserInformPath
...UserInformPath,
...UserAccountPath
};