From 049e1bef32c3f479305174c17ab0cb5124234be7 Mon Sep 17 00:00:00 2001 From: wkj <278599135@.com> Date: Thu, 12 Jun 2025 15:04:37 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4composeAccessPath=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E5=87=BA=E7=8E=B0=E5=A4=9A=E5=9F=9F=E5=90=8D?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- es/aspects/token.js | 18 ++++++---- es/checkers/index.d.ts | 2 +- es/components/changePassword/index.js | 23 ------------- .../config/style/platform/index.d.ts | 2 +- es/components/extraFile/commit/index.d.ts | 4 +-- es/components/user/password/update/index.js | 3 +- es/components/wechatLogin/qrCode/index.d.ts | 2 +- es/context/BackendRuntimeContext.d.ts | 1 + es/context/BackendRuntimeContext.js | 31 ++++++++++++++--- es/triggers/index.d.ts | 2 +- lib/aspects/session.js | 6 ++-- lib/aspects/token.js | 18 ++++++---- lib/aspects/wechatQrCode.js | 2 +- lib/context/BackendRuntimeContext.d.ts | 1 + lib/context/BackendRuntimeContext.js | 31 ++++++++++++++--- lib/triggers/index.d.ts | 2 +- lib/triggers/notification.js | 2 +- lib/triggers/toDo.d.ts | 2 +- src/aspects/token.ts | 14 +++++--- src/components/changePassword/index.ts | 25 -------------- src/components/user/password/update/index.ts | 4 ++- .../userRelation/upsert/onUser/web.pc.tsx | 3 +- src/context/BackendRuntimeContext.ts | 34 ++++++++++++++++--- 23 files changed, 136 insertions(+), 96 deletions(-) diff --git a/es/aspects/token.js b/es/aspects/token.js index 21b9de6e2..6571114d0 100644 --- a/es/aspects/token.js +++ b/es/aspects/token.js @@ -551,7 +551,7 @@ export async function verifyPassword(params, context) { }, {}); } export async function loginByAccount(params, context) { - const { account, password, env, } = params; + const { account, password, env } = params; let needUpdatePassword = false; const loginLogic = async () => { const systemId = context.getSystemId(); @@ -621,6 +621,7 @@ export async function loginByAccount(params, context) { data: { id: 1, password: 1, + passwordSha1: 1, email$user: { $entity: 'email', data: { @@ -678,7 +679,7 @@ export async function loginByAccount(params, context) { const allowEmail = !!applicationPassports.find((ele) => ele.passport?.type === 'email'); const [userRow] = result; const { email$user, id: userId, } = userRow; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); if (allowEmail) { const email = email$user?.find(ele => ele.email.toLowerCase() === account.toLowerCase()); if (email) { @@ -724,6 +725,7 @@ export async function loginByAccount(params, context) { data: { id: 1, password: 1, + passwordSha1: 1, mobile$user: { $entity: 'mobile', data: { @@ -780,7 +782,7 @@ export async function loginByAccount(params, context) { }); const [userRow] = result; const { mobile$user, id: userId, } = userRow; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); const allowSms = !!applicationPassports.find((ele) => ele.passport?.type === 'sms'); if (allowSms) { const mobile = mobile$user?.find(ele => ele.mobile === account); @@ -827,6 +829,7 @@ export async function loginByAccount(params, context) { data: { id: 1, password: 1, + passwordSha1: 1, loginName$user: { $entity: 'loginName', data: { @@ -862,7 +865,7 @@ export async function loginByAccount(params, context) { } case 1: { const [userRow] = result; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); const { loginName$user, id: userId, } = userRow; const loginName = loginName$user?.find((ele) => ele.name.toLowerCase() === account.toLowerCase()); if (loginName) { @@ -915,8 +918,9 @@ export async function loginByAccount(params, context) { await context.operate('user', { id: await generateNewIdAsync(), action: 'update', - data: password ? { + data: needUpdatePassword ? { password, + passwordSha1: encryptPasswordSha1(password), verifyPasswordAt: Date.now(), } : { verifyPasswordAt: Date.now(), @@ -2523,8 +2527,8 @@ export async function refreshToken(params, context) { // 只有server模式去刷新token // 'development' | 'production' | 'staging' const intervals = { - development: 7200 * 1000, - staging: 600 * 1000, + development: 7200 * 1000, // 2小时 + staging: 600 * 1000, // 十分钟 production: 600 * 1000, // 十分钟 }; let applicationId = token.applicationId; diff --git a/es/checkers/index.d.ts b/es/checkers/index.d.ts index 630f5dfe4..585d32c05 100644 --- a/es/checkers/index.d.ts +++ b/es/checkers/index.d.ts @@ -1,2 +1,2 @@ -declare const checkers: (import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker>)[]; +declare const checkers: (import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker> | import("oak-domain/lib/types").Checker>)[]; export default checkers; diff --git a/es/components/changePassword/index.js b/es/components/changePassword/index.js index d716200ca..e33f2aa0c 100644 --- a/es/components/changePassword/index.js +++ b/es/components/changePassword/index.js @@ -1,28 +1,5 @@ -const SEND_KEY = 'captcha:sendAt'; -const SEND_CAPTCHA_LATENCY = process.env.NODE_ENV === 'development' ? 10 : 60; export default OakComponent({ isList: false, - // entity: 'user', - // projection: { - // id: 1, - // name: 1, - // nickname: 1, - // mobile$user: { - // $entity: 'mobile', - // data: { - // id: 1, - // mobile: 1, - // }, - // filter: { - // ableState: 'enabled' - // } - // } - // }, - // formData: function ({ data: user, features, props }) { - // return { - // user, - // }; - // }, data: { channels: [], loading: false, diff --git a/es/components/config/style/platform/index.d.ts b/es/components/config/style/platform/index.d.ts index 2f2afe1c1..8835a6c5f 100644 --- a/es/components/config/style/platform/index.d.ts +++ b/es/components/config/style/platform/index.d.ts @@ -1,7 +1,7 @@ import { Style } from '../../../../types/Style'; declare const _default: (props: import("oak-frontend-base").ReactComponentProps) => React.ReactElement; diff --git a/es/components/extraFile/commit/index.d.ts b/es/components/extraFile/commit/index.d.ts index 83ea5c7c1..13cc84854 100644 --- a/es/components/extraFile/commit/index.d.ts +++ b/es/components/extraFile/commit/index.d.ts @@ -15,7 +15,7 @@ declare const _default: ) => unknown) | undefined; - type?: "submit" | "reset" | "button" | undefined; + type?: "button" | "submit" | "reset" | undefined; shape?: "default" | "rounded" | "rectangular" | undefined; children?: import("react").ReactNode; } & Pick & import("react").ButtonHTMLAttributes, "id" | "onMouseDown" | "onMouseUp" | "onTouchEnd" | "onTouchStart"> & { diff --git a/es/components/user/password/update/index.js b/es/components/user/password/update/index.js index c6e459df4..1a9bf0116 100644 --- a/es/components/user/password/update/index.js +++ b/es/components/user/password/update/index.js @@ -1,3 +1,4 @@ +import { encryptPasswordSha1 } from '../../../../utils/password'; export default OakComponent({ entity: 'user', projection: { @@ -77,7 +78,7 @@ export default OakComponent({ }, async commit() { const { pwd } = this.state; - this.update({ password: pwd }); + this.update({ password: pwd, passwordSha1: encryptPasswordSha1(pwd) }); await this.execute(); this.setState({ successful: true, diff --git a/es/components/wechatLogin/qrCode/index.d.ts b/es/components/wechatLogin/qrCode/index.d.ts index 21f928111..db7fcdc9b 100644 --- a/es/components/wechatLogin/qrCode/index.d.ts +++ b/es/components/wechatLogin/qrCode/index.d.ts @@ -1,6 +1,6 @@ import { EntityDict } from '../../../oak-app-domain'; declare const _default: (props: import("oak-frontend-base").ReactComponentProps) => React.ReactElement; diff --git a/es/context/BackendRuntimeContext.d.ts b/es/context/BackendRuntimeContext.d.ts index c6ef1d083..f512f132e 100644 --- a/es/context/BackendRuntimeContext.d.ts +++ b/es/context/BackendRuntimeContext.d.ts @@ -35,6 +35,7 @@ export declare abstract class BackendRuntimeContext>; allowUserUpdate(): boolean; + protected sortDomains(domains: ED['domain']['Schema'][]): ED['domain']['Schema'][]; /** * 获得当前系统的访问路径,根据application/system/domain之间的关联 * http://www.xxx.com/oak-api diff --git a/es/context/BackendRuntimeContext.js b/es/context/BackendRuntimeContext.js index a8d872090..d057c980b 100644 --- a/es/context/BackendRuntimeContext.js +++ b/es/context/BackendRuntimeContext.js @@ -11,6 +11,7 @@ import { cloneDeep, unset } from 'oak-domain/lib/utils/lodash'; import { composeServerUrl } from '../utils/domain'; import { maskPassword } from '../utils/user'; import { compareVersion } from 'oak-domain/lib/utils/version'; +import { isIP } from 'oak-domain/lib/utils/validator'; /** * general数据结构要求的后台上下文 */ @@ -406,17 +407,39 @@ export class BackendRuntimeContext extends BRC { } throw new OakUnloggedInException('您尚未登录'); } + sortDomains(domains) { + return domains.sort((a, b) => { + const getPriority = (domain) => { + if (typeof domain.url !== 'string') + return 3; + const lowerItem = domain.url.toLowerCase(); + // 1. 检查是否是localhost + if (lowerItem === 'localhost') + return 2; + // 2. 检查是否是IPv4或IPv6 + if (isIP(domain.url)) + return 1; + // 3. 其他情况认为是域名 + return 0; + }; + return getPriority(a) - getPriority(b); + }); + } /** * 获得当前系统的访问路径,根据application/system/domain之间的关联 * http://www.xxx.com/oak-api */ composeAccessPath() { const application = this.getApplication(); - const { system } = application; + const { system, domainId, domain } = application; + if (domainId) { + assert(domain); + return composeServerUrl(domain); + } const { domain$system: domains } = system; - assert(domains && domains.length === 1); - const [domain] = domains; - return composeServerUrl(domain); + assert(domains && domains.length > 0); + const findDomain = this.sortDomains(domains)?.[0]; + return composeServerUrl(findDomain); } async tryDeduceException(err) { if (this.application && this.appVersion) { diff --git a/es/triggers/index.d.ts b/es/triggers/index.d.ts index fc7f50979..425ea4be0 100644 --- a/es/triggers/index.d.ts +++ b/es/triggers/index.d.ts @@ -1,2 +1,2 @@ -declare const _default: (import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger>)[]; +declare const _default: (import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger>)[]; export default _default; diff --git a/lib/aspects/session.js b/lib/aspects/session.js index 0f5331d91..6b8e992f5 100644 --- a/lib/aspects/session.js +++ b/lib/aspects/session.js @@ -106,7 +106,7 @@ async function createSession(params, context) { origin: 'wechat', type: 'image', tag1: 'image', - objectId: await (0, uuid_1.generateNewIdAsync)(), + objectId: await (0, uuid_1.generateNewIdAsync)(), // 这个域用来标识唯一性 sort: 1000, uploadState: 'success', extra1: data.MediaId, @@ -131,7 +131,7 @@ async function createSession(params, context) { origin: 'wechat', type: 'video', tag1: 'video', - objectId: await (0, uuid_1.generateNewIdAsync)(), + objectId: await (0, uuid_1.generateNewIdAsync)(), // 这个域用来标识唯一性 sort: 1000, uploadState: 'success', extra1: data.MediaId, @@ -153,7 +153,7 @@ async function createSession(params, context) { origin: 'wechat', type: 'audio', tag1: 'audio', - objectId: await (0, uuid_1.generateNewIdAsync)(), + objectId: await (0, uuid_1.generateNewIdAsync)(), // 这个域用来标识唯一性 sort: 1000, uploadState: 'success', extra1: data.MediaId, diff --git a/lib/aspects/token.js b/lib/aspects/token.js index fa7ddc8d6..8a05143e5 100644 --- a/lib/aspects/token.js +++ b/lib/aspects/token.js @@ -557,7 +557,7 @@ async function verifyPassword(params, context) { } exports.verifyPassword = verifyPassword; async function loginByAccount(params, context) { - const { account, password, env, } = params; + const { account, password, env } = params; let needUpdatePassword = false; const loginLogic = async () => { const systemId = context.getSystemId(); @@ -627,6 +627,7 @@ async function loginByAccount(params, context) { data: { id: 1, password: 1, + passwordSha1: 1, email$user: { $entity: 'email', data: { @@ -684,7 +685,7 @@ async function loginByAccount(params, context) { const allowEmail = !!applicationPassports.find((ele) => ele.passport?.type === 'email'); const [userRow] = result; const { email$user, id: userId, } = userRow; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); if (allowEmail) { const email = email$user?.find(ele => ele.email.toLowerCase() === account.toLowerCase()); if (email) { @@ -730,6 +731,7 @@ async function loginByAccount(params, context) { data: { id: 1, password: 1, + passwordSha1: 1, mobile$user: { $entity: 'mobile', data: { @@ -786,7 +788,7 @@ async function loginByAccount(params, context) { }); const [userRow] = result; const { mobile$user, id: userId, } = userRow; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); const allowSms = !!applicationPassports.find((ele) => ele.passport?.type === 'sms'); if (allowSms) { const mobile = mobile$user?.find(ele => ele.mobile === account); @@ -833,6 +835,7 @@ async function loginByAccount(params, context) { data: { id: 1, password: 1, + passwordSha1: 1, loginName$user: { $entity: 'loginName', data: { @@ -868,7 +871,7 @@ async function loginByAccount(params, context) { } case 1: { const [userRow] = result; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); const { loginName$user, id: userId, } = userRow; const loginName = loginName$user?.find((ele) => ele.name.toLowerCase() === account.toLowerCase()); if (loginName) { @@ -921,8 +924,9 @@ async function loginByAccount(params, context) { await context.operate('user', { id: await (0, uuid_1.generateNewIdAsync)(), action: 'update', - data: password ? { + data: needUpdatePassword ? { password, + passwordSha1: (0, password_1.encryptPasswordSha1)(password), verifyPasswordAt: Date.now(), } : { verifyPasswordAt: Date.now(), @@ -2545,8 +2549,8 @@ async function refreshToken(params, context) { // 只有server模式去刷新token // 'development' | 'production' | 'staging' const intervals = { - development: 7200 * 1000, - staging: 600 * 1000, + development: 7200 * 1000, // 2小时 + staging: 600 * 1000, // 十分钟 production: 600 * 1000, // 十分钟 }; let applicationId = token.applicationId; diff --git a/lib/aspects/wechatQrCode.js b/lib/aspects/wechatQrCode.js index 02dcaf68e..ab0fc4df0 100644 --- a/lib/aspects/wechatQrCode.js +++ b/lib/aspects/wechatQrCode.js @@ -165,7 +165,7 @@ async function createWechatQrCode(options, context) { permanent, url, expired: false, - expiresAt: Date.now() + 2592000 * 1000, + expiresAt: Date.now() + 2592000 * 1000, // wecharQrCode里的过期时间都放到最大,由上层关联对象来主动过期(by Xc, 20230131) props, }; // 直接创建 diff --git a/lib/context/BackendRuntimeContext.d.ts b/lib/context/BackendRuntimeContext.d.ts index c6ef1d083..f512f132e 100644 --- a/lib/context/BackendRuntimeContext.d.ts +++ b/lib/context/BackendRuntimeContext.d.ts @@ -35,6 +35,7 @@ export declare abstract class BackendRuntimeContext>; allowUserUpdate(): boolean; + protected sortDomains(domains: ED['domain']['Schema'][]): ED['domain']['Schema'][]; /** * 获得当前系统的访问路径,根据application/system/domain之间的关联 * http://www.xxx.com/oak-api diff --git a/lib/context/BackendRuntimeContext.js b/lib/context/BackendRuntimeContext.js index b8ab5b420..9e2e745bc 100644 --- a/lib/context/BackendRuntimeContext.js +++ b/lib/context/BackendRuntimeContext.js @@ -14,6 +14,7 @@ const lodash_1 = require("oak-domain/lib/utils/lodash"); const domain_1 = require("../utils/domain"); const user_1 = require("../utils/user"); const version_1 = require("oak-domain/lib/utils/version"); +const validator_1 = require("oak-domain/lib/utils/validator"); /** * general数据结构要求的后台上下文 */ @@ -409,17 +410,39 @@ class BackendRuntimeContext extends BackendRuntimeContext_1.BackendRuntimeContex } throw new Exception_2.OakUnloggedInException('您尚未登录'); } + sortDomains(domains) { + return domains.sort((a, b) => { + const getPriority = (domain) => { + if (typeof domain.url !== 'string') + return 3; + const lowerItem = domain.url.toLowerCase(); + // 1. 检查是否是localhost + if (lowerItem === 'localhost') + return 2; + // 2. 检查是否是IPv4或IPv6 + if ((0, validator_1.isIP)(domain.url)) + return 1; + // 3. 其他情况认为是域名 + return 0; + }; + return getPriority(a) - getPriority(b); + }); + } /** * 获得当前系统的访问路径,根据application/system/domain之间的关联 * http://www.xxx.com/oak-api */ composeAccessPath() { const application = this.getApplication(); - const { system } = application; + const { system, domainId, domain } = application; + if (domainId) { + (0, assert_1.assert)(domain); + return (0, domain_1.composeServerUrl)(domain); + } const { domain$system: domains } = system; - (0, assert_1.assert)(domains && domains.length === 1); - const [domain] = domains; - return (0, domain_1.composeServerUrl)(domain); + (0, assert_1.assert)(domains && domains.length > 0); + const findDomain = this.sortDomains(domains)?.[0]; + return (0, domain_1.composeServerUrl)(findDomain); } async tryDeduceException(err) { if (this.application && this.appVersion) { diff --git a/lib/triggers/index.d.ts b/lib/triggers/index.d.ts index acc432115..fc7f50979 100644 --- a/lib/triggers/index.d.ts +++ b/lib/triggers/index.d.ts @@ -1,2 +1,2 @@ -declare const _default: (import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger>)[]; +declare const _default: (import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger> | import("oak-domain/lib/types").Trigger>)[]; export default _default; diff --git a/lib/triggers/notification.js b/lib/triggers/notification.js index 594d30e40..ca7df6315 100644 --- a/lib/triggers/notification.js +++ b/lib/triggers/notification.js @@ -64,7 +64,7 @@ async function sendNotification(notification, context) { await instance.sendSubscribedMessage({ templateId: templateId, data: data, - openId: data1.openId, + openId: data1.openId, // 在notification创建时就赋值了 page, state: StateDict[process.env.NODE_ENV], }); diff --git a/lib/triggers/toDo.d.ts b/lib/triggers/toDo.d.ts index e5be399e1..1d9bc2ce2 100644 --- a/lib/triggers/toDo.d.ts +++ b/lib/triggers/toDo.d.ts @@ -14,7 +14,7 @@ export declare function createToDo; +}, userIds?: string[]): Promise<0 | 1>; /** * 完成todo例程,当在entity对象上进行action操作时(操作条件是filter),将对应的todo完成 * 必须在entity的action的后trigger中调用 diff --git a/src/aspects/token.ts b/src/aspects/token.ts index cbb4bff39..cef139478 100644 --- a/src/aspects/token.ts +++ b/src/aspects/token.ts @@ -752,7 +752,7 @@ export async function loginByAccount( }, context: BRC ): Promise { - const { account, password, env, } = params; + const { account, password, env } = params; let needUpdatePassword = false; const loginLogic = async () => { @@ -830,6 +830,7 @@ export async function loginByAccount( data: { id: 1, password: 1, + passwordSha1: 1, email$user: { $entity: 'email', data: { @@ -893,7 +894,7 @@ export async function loginByAccount( const allowEmail = !!applicationPassports.find((ele) => ele.passport?.type === 'email'); const [userRow] = result; const { email$user, id: userId, } = userRow; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); if (allowEmail) { const email = email$user?.find(ele => ele.email.toLowerCase() === account.toLowerCase()); if (email) { @@ -945,6 +946,7 @@ export async function loginByAccount( data: { id: 1, password: 1, + passwordSha1: 1, mobile$user: { $entity: 'mobile', data: { @@ -1008,7 +1010,7 @@ export async function loginByAccount( ); const [userRow] = result; const { mobile$user, id: userId, } = userRow; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); const allowSms = !!applicationPassports.find((ele) => ele.passport?.type === 'sms'); if (allowSms) { @@ -1062,6 +1064,7 @@ export async function loginByAccount( data: { id: 1, password: 1, + passwordSha1: 1, loginName$user: { $entity: 'loginName', data: { @@ -1100,7 +1103,7 @@ export async function loginByAccount( } case 1: { const [userRow] = result; - needUpdatePassword = !userRow.password; + needUpdatePassword = !(userRow.password || userRow.passwordSha1); const { loginName$user, id: userId, } = userRow; const loginName = loginName$user?.find((ele) => ele.name.toLowerCase() === account.toLowerCase()); if (loginName) { @@ -1160,8 +1163,9 @@ export async function loginByAccount( await context.operate('user', { id: await generateNewIdAsync(), action: 'update', - data: password ? { + data: needUpdatePassword ? { password, + passwordSha1: encryptPasswordSha1(password), verifyPasswordAt: Date.now(), }: { verifyPasswordAt: Date.now(), diff --git a/src/components/changePassword/index.ts b/src/components/changePassword/index.ts index a57050b16..c9644c21a 100644 --- a/src/components/changePassword/index.ts +++ b/src/components/changePassword/index.ts @@ -1,31 +1,6 @@ -import { encryptPasswordSha1 } from '../../utils/password'; -import dayjs from 'dayjs'; -const SEND_KEY = 'captcha:sendAt'; -const SEND_CAPTCHA_LATENCY = process.env.NODE_ENV === 'development' ? 10 : 60; export default OakComponent({ isList: false, - // entity: 'user', - // projection: { - // id: 1, - // name: 1, - // nickname: 1, - // mobile$user: { - // $entity: 'mobile', - // data: { - // id: 1, - // mobile: 1, - // }, - // filter: { - // ableState: 'enabled' - // } - // } - // }, - // formData: function ({ data: user, features, props }) { - // return { - // user, - // }; - // }, data: { channels: [] as string[], loading: false, diff --git a/src/components/user/password/update/index.ts b/src/components/user/password/update/index.ts index 449c1578c..2e668f75b 100644 --- a/src/components/user/password/update/index.ts +++ b/src/components/user/password/update/index.ts @@ -1,3 +1,5 @@ +import { encryptPasswordSha1 } from '../../../../utils/password'; + export default OakComponent({ entity: 'user', projection: { @@ -78,7 +80,7 @@ export default OakComponent({ }, async commit() { const { pwd } = this.state; - this.update({ password: pwd }); + this.update({ password: pwd, passwordSha1: encryptPasswordSha1(pwd!) }); await this.execute(); this.setState({ successful: true, diff --git a/src/components/userRelation/upsert/onUser/web.pc.tsx b/src/components/userRelation/upsert/onUser/web.pc.tsx index 034108667..2ecaeb843 100644 --- a/src/components/userRelation/upsert/onUser/web.pc.tsx +++ b/src/components/userRelation/upsert/onUser/web.pc.tsx @@ -234,8 +234,7 @@ export default function Render( setPassword2(strValue); if (password === strValue) { update({ - passwordSha1: - encryptPasswordSha1(password), + passwordSha1: encryptPasswordSha1(password), }); } setPasswordConfirm( diff --git a/src/context/BackendRuntimeContext.ts b/src/context/BackendRuntimeContext.ts index 1db626fff..9f7ed823d 100644 --- a/src/context/BackendRuntimeContext.ts +++ b/src/context/BackendRuntimeContext.ts @@ -23,6 +23,7 @@ import { cloneDeep, unset } from 'oak-domain/lib/utils/lodash'; import { composeServerUrl } from '../utils/domain'; import { maskPassword } from '../utils/user'; import { compareVersion } from 'oak-domain/lib/utils/version'; +import { isIP } from 'oak-domain/lib/utils/validator'; /** * general数据结构要求的后台上下文 */ @@ -478,18 +479,43 @@ export abstract class BackendRuntimeContext { + const getPriority = (domain: EntityDict['domain']['Schema']) => { + if (typeof domain.url !== 'string') return 3; + const lowerItem = domain.url.toLowerCase(); + + // 1. 检查是否是localhost + if (lowerItem === 'localhost') return 2; + + // 2. 检查是否是IPv4或IPv6 + if (isIP(domain.url)) return 1; + + // 3. 其他情况认为是域名 + return 0; + }; + + return getPriority(a) - getPriority(b); + }); + } + + /** * 获得当前系统的访问路径,根据application/system/domain之间的关联 * http://www.xxx.com/oak-api */ composeAccessPath(): string { const application = this.getApplication(); - const { system } = application!; + const { system, domainId, domain } = application!; + if (domainId) { + assert(domain); + return composeServerUrl(domain as EntityDict['domain']['Schema']); + } const { domain$system: domains } = system!; - assert(domains && domains.length === 1); - const [ domain ] = domains; + assert(domains && domains.length > 0); + const findDomain = this.sortDomains(domains as EntityDict['domain']['Schema'][])?.[0]; - return composeServerUrl(domain as EntityDict['domain']['Schema']); + return composeServerUrl(findDomain as EntityDict['domain']['Schema']); } async tryDeduceException(err: Error): Promise | void> {