登录修改
This commit is contained in:
parent
48bddab812
commit
5157bc73f3
|
|
@ -22,9 +22,8 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
) => Promise<string>;
|
||||
loginByMobile: (
|
||||
params: {
|
||||
captcha?: string;
|
||||
password?: string;
|
||||
mobile: string;
|
||||
captcha: string;
|
||||
disableRegister?: boolean;
|
||||
env: WebEnv | WechatMpEnv | NativeEnv;
|
||||
},
|
||||
|
|
@ -34,7 +33,6 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
params: {
|
||||
account: string;
|
||||
password: string;
|
||||
disableRegister?: boolean;
|
||||
env: WebEnv | WechatMpEnv | NativeEnv;
|
||||
},
|
||||
context: BackendRuntimeContext<ED>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import { mergeUser } from './user';
|
|||
import { cloneDeep, pick } from 'oak-domain/lib/utils/lodash';
|
||||
import { BRC } from '../types/RuntimeCxt';
|
||||
import { SmsConfig } from '../entities/Passport';
|
||||
import { sendEmail } from '../utils/email';
|
||||
import { sendEmail } from '../utils/email/index.backend';
|
||||
import { EmailConfig } from '../oak-app-domain/Passport/Schema';
|
||||
import { isEmail, isMobile } from 'oak-domain/lib/utils/validator';
|
||||
|
||||
|
|
@ -584,112 +584,55 @@ async function loadTokenInfo<ED extends EntityDict>(tokenValue: string, context:
|
|||
|
||||
export async function loginByMobile<ED extends EntityDict>(
|
||||
params: {
|
||||
captcha?: string;
|
||||
password?: string;
|
||||
mobile: string;
|
||||
captcha: string;
|
||||
disableRegister?: boolean;
|
||||
env: WebEnv | WechatMpEnv | NativeEnv;
|
||||
},
|
||||
context: BRC<ED>
|
||||
): Promise<string> {
|
||||
const { mobile, captcha, password, env, disableRegister } = params;
|
||||
const { mobile, captcha, env, disableRegister } = params;
|
||||
|
||||
const loginLogic = async () => {
|
||||
const systemId = context.getSystemId();
|
||||
if (captcha) {
|
||||
const result = await context.select(
|
||||
'captcha',
|
||||
{
|
||||
data: {
|
||||
id: 1,
|
||||
expired: 1,
|
||||
},
|
||||
filter: {
|
||||
origin: 'mobile',
|
||||
content: mobile,
|
||||
code: captcha,
|
||||
},
|
||||
sorter: [
|
||||
{
|
||||
$attr: {
|
||||
$$createAt$$: 1,
|
||||
},
|
||||
$direction: 'desc',
|
||||
},
|
||||
],
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
const result = await context.select(
|
||||
'captcha',
|
||||
{
|
||||
data: {
|
||||
id: 1,
|
||||
expired: 1,
|
||||
},
|
||||
{ dontCollect: true }
|
||||
);
|
||||
if (result.length > 0) {
|
||||
const [captchaRow] = result;
|
||||
if (captchaRow.expired) {
|
||||
throw new OakUserException('验证码已经过期');
|
||||
}
|
||||
filter: {
|
||||
origin: 'mobile',
|
||||
content: mobile,
|
||||
code: captcha,
|
||||
},
|
||||
sorter: [
|
||||
{
|
||||
$attr: {
|
||||
$$createAt$$: 1,
|
||||
},
|
||||
$direction: 'desc',
|
||||
},
|
||||
],
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
},
|
||||
{ dontCollect: true }
|
||||
);
|
||||
if (result.length > 0) {
|
||||
const [captchaRow] = result;
|
||||
if (captchaRow.expired) {
|
||||
throw new OakUserException('验证码已经过期');
|
||||
}
|
||||
|
||||
// 到这里说明验证码已经通过
|
||||
return await setupMobile<ED>(mobile, env, context);
|
||||
} else {
|
||||
throw new OakUserException('验证码无效');
|
||||
}
|
||||
// 到这里说明验证码已经通过
|
||||
return await setupMobile<ED>(mobile, env, context);
|
||||
} else {
|
||||
assert(password);
|
||||
const result = await context.select(
|
||||
'mobile',
|
||||
{
|
||||
data: {
|
||||
id: 1,
|
||||
userId: 1,
|
||||
ableState: 1,
|
||||
},
|
||||
filter: {
|
||||
mobile: mobile,
|
||||
user: {
|
||||
$or: [
|
||||
{
|
||||
password,
|
||||
},
|
||||
{
|
||||
passwordSha1: encryptPasswordSha1(password),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
dontCollect: true,
|
||||
}
|
||||
);
|
||||
switch (result.length) {
|
||||
case 0: {
|
||||
throw new OakUserException('用户名与密码不匹配');
|
||||
}
|
||||
case 1: {
|
||||
const [mobileRow] = result;
|
||||
const { ableState, userId } = mobileRow;
|
||||
if (ableState === 'disabled') {
|
||||
// 虽然密码和手机号匹配,但手机号已经禁用了,在可能的情况下提醒用户使用其它方法登录
|
||||
const exception = await tryMakeChangeLoginWay<ED>(
|
||||
userId as string,
|
||||
context
|
||||
);
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
return await setupMobile<ED>(mobile, env, context);
|
||||
}
|
||||
default: {
|
||||
throw new Error(
|
||||
`手机号和密码匹配出现雷同,mobile id是[${result
|
||||
.map((ele) => ele.id)
|
||||
.join(',')}], mobile是${mobile}`
|
||||
);
|
||||
}
|
||||
}
|
||||
throw new OakUserException('验证码无效');
|
||||
}
|
||||
};
|
||||
|
||||
const closeRootMode = context.openRootMode();
|
||||
if (disableRegister) {
|
||||
const [existMobile] = await context.select(
|
||||
|
|
@ -722,12 +665,11 @@ export async function loginByAccount<ED extends EntityDict>(
|
|||
params: {
|
||||
account: string;
|
||||
password: string;
|
||||
disableRegister?: boolean;
|
||||
env: WebEnv | WechatMpEnv | NativeEnv;
|
||||
},
|
||||
context: BRC<ED>
|
||||
): Promise<string> {
|
||||
const { account, password, env, disableRegister } = params;
|
||||
const { account, password, env, } = params;
|
||||
|
||||
const loginLogic = async () => {
|
||||
const systemId = context.getSystemId();
|
||||
|
|
@ -752,6 +694,14 @@ export async function loginByAccount<ED extends EntityDict>(
|
|||
email: 1,
|
||||
ableState: 1,
|
||||
}
|
||||
},
|
||||
loginName$user: {
|
||||
$entity: 'loginName',
|
||||
data: {
|
||||
id: 1,
|
||||
name: 1,
|
||||
ableState: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
|
|
@ -768,6 +718,11 @@ export async function loginByAccount<ED extends EntityDict>(
|
|||
email: account,
|
||||
}
|
||||
},
|
||||
{
|
||||
loginName$user: {
|
||||
name: account,
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -790,11 +745,11 @@ export async function loginByAccount<ED extends EntityDict>(
|
|||
);
|
||||
switch (result.length) {
|
||||
case 0: {
|
||||
throw new OakUserException('用户名与密码不匹配');
|
||||
throw new OakUserException('账号与密码不匹配');
|
||||
}
|
||||
case 1: {
|
||||
const [userRow] = result;
|
||||
const { mobile$user, email$user, id: userId, } = userRow;
|
||||
const { mobile$user, email$user, loginName$user, id: userId, } = userRow;
|
||||
if (mobile$user && mobile$user.length > 0) {
|
||||
const ableState = mobile$user[0].ableState;
|
||||
if (ableState === 'disabled') {
|
||||
|
|
@ -821,79 +776,28 @@ export async function loginByAccount<ED extends EntityDict>(
|
|||
}
|
||||
}
|
||||
return await setupEmail<ED>(account, env, context);
|
||||
} else if (loginName$user && loginName$user.length > 0) {
|
||||
const ableState = loginName$user[0].ableState;
|
||||
if (ableState === 'disabled') {
|
||||
// 虽然密码和邮箱匹配,但邮箱已经禁用了,在可能的情况下提醒用户使用其它方法登录
|
||||
const exception = await tryMakeChangeLoginWay<ED>(
|
||||
userId as string,
|
||||
context
|
||||
);
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
return await setupLoginName<ED>(account, env, context);
|
||||
}
|
||||
return ''
|
||||
}
|
||||
default: {
|
||||
throw new Error(
|
||||
// `手机号和密码匹配出现雷同,mobile id是[${result
|
||||
// .map((ele) => ele.id)
|
||||
// .join(',')}], mobile是${mobile}`
|
||||
);
|
||||
throw new Error('不支持的登录方式');
|
||||
}
|
||||
}
|
||||
};
|
||||
const closeRootMode = context.openRootMode();
|
||||
if (disableRegister) {
|
||||
if (isMobile(account)) {
|
||||
const [existMobile] = await context.select(
|
||||
'mobile',
|
||||
{
|
||||
data: {
|
||||
id: 1,
|
||||
mobile: 1,
|
||||
},
|
||||
filter: {
|
||||
mobile: account!,
|
||||
ableState: 'enabled',
|
||||
},
|
||||
},
|
||||
{ dontCollect: true }
|
||||
);
|
||||
if (!existMobile) {
|
||||
closeRootMode();
|
||||
throw new OakUserException('账号不存在');
|
||||
}
|
||||
} else if (isEmail(account)) {
|
||||
const [existEmail] = await context.select(
|
||||
'email',
|
||||
{
|
||||
data: {
|
||||
id: 1,
|
||||
email: 1,
|
||||
},
|
||||
filter: {
|
||||
email: account!,
|
||||
ableState: 'enabled',
|
||||
},
|
||||
},
|
||||
{ dontCollect: true }
|
||||
);
|
||||
if (!existEmail) {
|
||||
closeRootMode();
|
||||
throw new OakUserException('账号不存在');
|
||||
}
|
||||
} else {
|
||||
// const [existMobile] = await context.select(
|
||||
// 'mobile',
|
||||
// {
|
||||
// data: {
|
||||
// id: 1,
|
||||
// mobile: 1,
|
||||
// },
|
||||
// filter: {
|
||||
// mobile: mobile!,
|
||||
// ableState: 'enabled',
|
||||
// },
|
||||
// },
|
||||
// { dontCollect: true }
|
||||
// );
|
||||
// if (!existMobile) {
|
||||
// closeRootMode();
|
||||
// throw new OakUserException('账号不存在');
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
const tokenValue = await loginLogic();
|
||||
await loadTokenInfo<ED>(tokenValue, context);
|
||||
closeRootMode();
|
||||
|
|
@ -979,6 +883,70 @@ export async function loginByEmail<ED extends EntityDict>(
|
|||
return tokenValue;
|
||||
}
|
||||
|
||||
async function setupLoginName<ED extends EntityDict>(name: string, env: WebEnv | WechatMpEnv | NativeEnv, context: BRC<ED>) {
|
||||
const result2 = await context.select(
|
||||
'loginName',
|
||||
{
|
||||
data: {
|
||||
id: 1,
|
||||
name: 1,
|
||||
userId: 1,
|
||||
ableState: 1,
|
||||
user: {
|
||||
id: 1,
|
||||
userState: 1,
|
||||
refId: 1,
|
||||
ref: {
|
||||
id: 1,
|
||||
userState: 1,
|
||||
refId: 1,
|
||||
},
|
||||
wechatUser$user: {
|
||||
$entity: 'wechatUser',
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
},
|
||||
userSystem$user: {
|
||||
$entity: 'userSystem',
|
||||
data: {
|
||||
id: 1,
|
||||
systemId: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
name,
|
||||
ableState: 'enabled',
|
||||
},
|
||||
},
|
||||
{ dontCollect: true }
|
||||
);
|
||||
assert(result2.length === 1);
|
||||
const [loginNameRow] = result2;
|
||||
const { user } = loginNameRow;
|
||||
const { userState, ref } = user!;
|
||||
if (userState === 'merged') {
|
||||
return await setUpTokenAndUser<ED>(
|
||||
env,
|
||||
context,
|
||||
'loginName',
|
||||
loginNameRow.id,
|
||||
undefined,
|
||||
ref as Partial<ED['user']['Schema']>
|
||||
);
|
||||
}
|
||||
return await setUpTokenAndUser<ED>(
|
||||
env,
|
||||
context,
|
||||
'loginName',
|
||||
loginNameRow.id,
|
||||
undefined,
|
||||
user as Partial<ED['user']['Schema']>
|
||||
);
|
||||
}
|
||||
|
||||
async function setupEmail<ED extends EntityDict>(email: string, env: WebEnv | WechatMpEnv | NativeEnv, context: BRC<ED>) {
|
||||
const result2 = await context.select(
|
||||
'email',
|
||||
|
|
@ -2088,6 +2056,18 @@ export async function sendCaptchaByEmail<ED extends EntityDict>(
|
|||
const duration = config.codeDuration || 5;
|
||||
const digit = config.digit || 4;
|
||||
|
||||
let emailOptions = {
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
account: config.account,
|
||||
password: config.password,
|
||||
subject: config.subject,
|
||||
from: config.name ? `"${config.name}" <${config.account}>` : config.account,
|
||||
to: email,
|
||||
text: config.text,
|
||||
html: config.html,
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const closeRootMode = context.openRootMode();
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
|
|
@ -2153,26 +2133,24 @@ export async function sendCaptchaByEmail<ED extends EntityDict>(
|
|||
);
|
||||
if (captcha) {
|
||||
const code = captcha.code!;
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
closeRootMode();
|
||||
return `验证码[${code}]已创建`;
|
||||
} else if (now - (captcha.$$createAt$$! as number) < 60000) {
|
||||
// if (process.env.NODE_ENV === 'development') {
|
||||
// closeRootMode();
|
||||
// return `验证码[${code}]已创建`;
|
||||
// } else
|
||||
if (now - (captcha.$$createAt$$! as number) < 60000) {
|
||||
closeRootMode();
|
||||
throw new OakUserException('您的操作太迅捷啦,请稍等再点吧');
|
||||
} else {
|
||||
assert(config.account, '必须设置邮箱');
|
||||
// todo 再次发送
|
||||
const text = config.text?.replace('${duration}', duration.toString() + '分钟').replace('${code}', code);
|
||||
const html = config.html?.replace('${duration}', duration.toString() + '分钟').replace('${code}', code);
|
||||
emailOptions.text = text;
|
||||
emailOptions.html = html;
|
||||
const result = await sendEmail(
|
||||
config.host,
|
||||
config.port,
|
||||
config.account,
|
||||
config.password,
|
||||
config.subject,
|
||||
email,
|
||||
config.name,
|
||||
config.text,
|
||||
config.html,
|
||||
{ code, duration: duration.toString() },
|
||||
{
|
||||
...emailOptions,
|
||||
}
|
||||
);
|
||||
closeRootMode();
|
||||
if (result.success) {
|
||||
|
|
@ -2209,30 +2187,27 @@ export async function sendCaptchaByEmail<ED extends EntityDict>(
|
|||
}
|
||||
);
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
closeRootMode();
|
||||
return `验证码[${code}]已创建`;
|
||||
} else {
|
||||
assert(config.account, '必须设置邮箱');
|
||||
//发送邮件
|
||||
const result = await sendEmail(
|
||||
config.host,
|
||||
config.port,
|
||||
config.account,
|
||||
config.password,
|
||||
config.subject,
|
||||
email,
|
||||
config.name,
|
||||
config.text,
|
||||
config.html,
|
||||
{ code, duration: duration.toString() },
|
||||
);
|
||||
closeRootMode();
|
||||
if (result.success) {
|
||||
return '验证码已发送';
|
||||
// if (process.env.NODE_ENV === 'development') {
|
||||
// closeRootMode();
|
||||
// return `验证码[${code}]已创建`;
|
||||
// } else {
|
||||
assert(config.account, '必须设置邮箱');
|
||||
//发送邮件
|
||||
const text = config.text?.replace('${duration}', duration.toString() + '分钟').replace('${code}', code);
|
||||
const html = config.html?.replace('${duration}', duration.toString() + '分钟').replace('${code}', code);
|
||||
emailOptions.text = text;
|
||||
emailOptions.html = html;
|
||||
const result = await sendEmail(
|
||||
{
|
||||
...emailOptions,
|
||||
}
|
||||
return '验证码发送失败';
|
||||
);
|
||||
closeRootMode();
|
||||
if (result.success) {
|
||||
return '验证码已发送';
|
||||
}
|
||||
return '验证码发送失败';
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,11 +90,10 @@ export default OakComponent({
|
|||
},
|
||||
async loginByMobile() {
|
||||
const { eventLoggedIn, callback } = this.props;
|
||||
const { mobile, password, captcha } = this.state;
|
||||
const { mobile,captcha } = this.state;
|
||||
try {
|
||||
await this.features.token.loginByMobile(
|
||||
mobile,
|
||||
password,
|
||||
captcha
|
||||
);
|
||||
if (typeof callback === 'function') {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export default OakComponent({
|
|||
password: '',
|
||||
validMobile: false,
|
||||
vaildEmail: false,
|
||||
vaildAccount: false,
|
||||
validPassword: false,
|
||||
allowSubmit: false,
|
||||
},
|
||||
|
|
@ -34,16 +35,16 @@ export default OakComponent({
|
|||
lifetimes: {
|
||||
},
|
||||
listeners: {
|
||||
'validMobile,vaildEmail,validPassword'(prev, next) {
|
||||
'vaildAccount,validPassword'(prev, next) {
|
||||
const { allowSubmit } = this.state;
|
||||
if (allowSubmit) {
|
||||
if (!((next.validMobile || next.vaildEmail) && next.validPassword)) {
|
||||
if (!(next.vaildAccount && next.validPassword)) {
|
||||
this.setState({
|
||||
allowSubmit: false,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if ((next.validMobile || next.vaildEmail) && next.validPassword) {
|
||||
if (next.vaildAccount && next.validPassword) {
|
||||
this.setState({
|
||||
allowSubmit: true,
|
||||
})
|
||||
|
|
@ -52,7 +53,7 @@ export default OakComponent({
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
async loginByPassword() {
|
||||
async loginByAccount() {
|
||||
const { url, callback } = this.props;
|
||||
const { account, password } = this.state;
|
||||
try {
|
||||
|
|
@ -90,12 +91,14 @@ export default OakComponent({
|
|||
const { allowSms, allowEmail } = this.props;
|
||||
switch (type) {
|
||||
case 'account':
|
||||
const validMobile = allowSms && !!isMobile(value);
|
||||
const vaildEmail = allowEmail && !!isEmail(value);
|
||||
// const validMobile = allowSms && !!isMobile(value);
|
||||
// const vaildEmail = allowEmail && !!isEmail(value);
|
||||
const vaildAccount = !!(value && value.trim() && value.trim() !== '');
|
||||
this.setState({
|
||||
account: value,
|
||||
validMobile,
|
||||
vaildEmail,
|
||||
// validMobile,
|
||||
// vaildEmail,
|
||||
vaildAccount,
|
||||
})
|
||||
break;
|
||||
case 'password':
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ export default OakComponent({
|
|||
});
|
||||
await this.features.token.loginByMobile(
|
||||
mobile,
|
||||
undefined,
|
||||
captcha
|
||||
);
|
||||
this.setState({
|
||||
|
|
|
|||
Loading…
Reference in New Issue