mergeUser逻辑增强

This commit is contained in:
Xu Chang 2023-12-20 20:58:02 +08:00
parent 76abf88025
commit 4b5de1a315
12 changed files with 221 additions and 85 deletions

View File

@ -125,6 +125,10 @@ async function dealWithUserState(user, context, tokenData) {
}
}
}
function autoMergeUser(context) {
const { system } = context.getApplication();
return !!system.config.App.mergeUserDirectly;
}
/**
* 根据user的不同情况完成登录动作
* @param env
@ -153,25 +157,21 @@ createData, user) {
if (currentToken.userId === user.id) {
return currentToken.id;
}
await mergeUser({ from: user.id, to: currentToken.userId }, context, true);
return currentToken.id;
const autoMerge = autoMergeUser(context);
if (autoMerge) {
await mergeUser({ from: user.id, to: currentToken.userId, mergeMobile: true, mergeWechatUser: true, mergeEmail: true }, context, true);
return currentToken.id;
}
throw await makeDistinguishException(user.id, context);
}
case 'shadow': {
assert(currentToken.userId !== user.id);
await mergeUser({ from: user.id, to: currentToken.userId }, context, true);
// await context.operate(
// 'user',
// {
// id: await generateNewIdAsync(),
// action: 'activate',
// data: {},
// filter: {
// id: user.id!,
// },
// },
// { dontCollect: true }
// );
return currentToken.id;
const autoMerge = autoMergeUser(context);
if (autoMerge) {
await mergeUser({ from: user.id, to: currentToken.userId, mergeMobile: true, mergeWechatUser: true, mergeEmail: true }, context, true);
return currentToken.id;
}
throw await makeDistinguishException(user.id, context);
}
case 'disabled': {
throw new OakUserDisabledException();
@ -181,10 +181,14 @@ createData, user) {
if (user.refId === currentToken.userId) {
return currentToken.id;
}
// 说明一个用户被其他用户merge了现在还是暂时先merge后面再说
console.warn(`用户${user.id}已经是merged状态「${user.refId}再次被merged到「${currentToken.userId}]」`);
await mergeUser({ from: user.id, to: currentToken.userId }, context, true);
return currentToken.id;
const autoMerge = autoMergeUser(context);
if (autoMerge) {
// 说明一个用户被其他用户merge了现在还是暂时先merge后面再说
console.warn(`用户${user.id}已经是merged状态「${user.refId}再次被merged到「${currentToken.userId}]」`);
await mergeUser({ from: user.id, to: currentToken.userId, mergeMobile: true, mergeWechatUser: true, mergeEmail: true }, context, true);
return currentToken.id;
}
throw await makeDistinguishException(user.id, context);
}
default: {
assert(false, `不能理解的user状态「${userState}`);

View File

@ -4,6 +4,9 @@ import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
export declare function mergeUser<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>>(params: {
from: string;
to: string;
mergeMobile?: true;
mergeEmail?: true;
mergeWechatUser?: true;
}, context: Cxt, innerLogic?: boolean): Promise<void>;
export declare function getChangePasswordChannels<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>>(params: {
userId: string;

View File

@ -7,7 +7,7 @@ export async function mergeUser(params, context, innerLogic) {
if (!innerLogic && !context.isRoot()) {
throw new OakUserUnpermittedException('不允许执行mergeUser操作');
}
const { from, to } = params;
const { from, to, mergeMobile, mergeEmail, mergeWechatUser } = params;
assert(from);
assert(to);
assert(from !== to, '不能merge到相同user');
@ -77,6 +77,42 @@ export async function mergeUser(params, context, innerLogic) {
],
},
}, {});
if (mergeEmail) {
await context.operate('email', {
id: await generateNewIdAsync(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
if (mergeMobile) {
await context.operate('mobile', {
id: await generateNewIdAsync(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
if (mergeWechatUser) {
await context.operate('wechatUser', {
id: await generateNewIdAsync(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
}
export async function getChangePasswordChannels(params, context, innerLogic) {
const { userId } = params;

View File

@ -1,7 +1,7 @@
import { Style } from '../../../../types/Style';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../../oak-app-domain").EntityDict, keyof import("../../../../oak-app-domain").EntityDict, false, {
style: Style;
entity: "platform" | "application" | "system";
entity: "application" | "platform" | "system";
entityId: string;
name: string;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;

View File

@ -12,19 +12,19 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
type?: ButtonProps['type'] | AmButtonProps['type'];
executeText?: string | undefined;
buttonProps?: (ButtonProps & {
color?: "default" | "success" | "warning" | "primary" | "danger" | undefined;
color?: "success" | "default" | "warning" | "primary" | "danger" | undefined;
fill?: "none" | "solid" | "outline" | undefined;
size?: "small" | "large" | "middle" | "mini" | undefined;
size?: "small" | "middle" | "large" | "mini" | undefined;
block?: boolean | undefined;
loading?: boolean | "auto" | undefined;
loadingText?: string | undefined;
loadingIcon?: import("react").ReactNode;
disabled?: boolean | undefined;
onClick?: ((event: import("react").MouseEvent<HTMLButtonElement, MouseEvent>) => unknown) | undefined;
type?: "button" | "submit" | "reset" | undefined;
type?: "button" | "reset" | "submit" | undefined;
shape?: "default" | "rounded" | "rectangular" | undefined;
children?: import("react").ReactNode;
} & Pick<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement>, "id" | "onMouseUp" | "onMouseDown" | "onTouchStart" | "onTouchEnd"> & {
} & Pick<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement>, "id" | "onMouseDown" | "onMouseUp" | "onTouchStart" | "onTouchEnd"> & {
className?: string | undefined;
style?: (import("react").CSSProperties & Partial<Record<"--text-color" | "--background-color" | "--border-radius" | "--border-width" | "--border-style" | "--border-color", string>>) | undefined;
tabIndex?: number | undefined;

View File

@ -1,2 +1,2 @@
declare const _default: (import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "account", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>>)[];
declare const _default: (import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "account", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>>)[];
export default _default;

View File

@ -128,6 +128,10 @@ async function dealWithUserState(user, context, tokenData) {
}
}
}
function autoMergeUser(context) {
const { system } = context.getApplication();
return !!system.config.App.mergeUserDirectly;
}
/**
* 根据user的不同情况完成登录动作
* @param env
@ -156,25 +160,21 @@ createData, user) {
if (currentToken.userId === user.id) {
return currentToken.id;
}
await (0, user_1.mergeUser)({ from: user.id, to: currentToken.userId }, context, true);
return currentToken.id;
const autoMerge = autoMergeUser(context);
if (autoMerge) {
await (0, user_1.mergeUser)({ from: user.id, to: currentToken.userId, mergeMobile: true, mergeWechatUser: true, mergeEmail: true }, context, true);
return currentToken.id;
}
throw await makeDistinguishException(user.id, context);
}
case 'shadow': {
(0, assert_1.assert)(currentToken.userId !== user.id);
await (0, user_1.mergeUser)({ from: user.id, to: currentToken.userId }, context, true);
// await context.operate(
// 'user',
// {
// id: await generateNewIdAsync(),
// action: 'activate',
// data: {},
// filter: {
// id: user.id!,
// },
// },
// { dontCollect: true }
// );
return currentToken.id;
const autoMerge = autoMergeUser(context);
if (autoMerge) {
await (0, user_1.mergeUser)({ from: user.id, to: currentToken.userId, mergeMobile: true, mergeWechatUser: true, mergeEmail: true }, context, true);
return currentToken.id;
}
throw await makeDistinguishException(user.id, context);
}
case 'disabled': {
throw new Exception_1.OakUserDisabledException();
@ -184,10 +184,14 @@ createData, user) {
if (user.refId === currentToken.userId) {
return currentToken.id;
}
// 说明一个用户被其他用户merge了现在还是暂时先merge后面再说
console.warn(`用户${user.id}已经是merged状态「${user.refId}再次被merged到「${currentToken.userId}]」`);
await (0, user_1.mergeUser)({ from: user.id, to: currentToken.userId }, context, true);
return currentToken.id;
const autoMerge = autoMergeUser(context);
if (autoMerge) {
// 说明一个用户被其他用户merge了现在还是暂时先merge后面再说
console.warn(`用户${user.id}已经是merged状态「${user.refId}再次被merged到「${currentToken.userId}]」`);
await (0, user_1.mergeUser)({ from: user.id, to: currentToken.userId, mergeMobile: true, mergeWechatUser: true, mergeEmail: true }, context, true);
return currentToken.id;
}
throw await makeDistinguishException(user.id, context);
}
default: {
(0, assert_1.assert)(false, `不能理解的user状态「${userState}`);

View File

@ -4,6 +4,9 @@ import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
export declare function mergeUser<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>>(params: {
from: string;
to: string;
mergeMobile?: true;
mergeEmail?: true;
mergeWechatUser?: true;
}, context: Cxt, innerLogic?: boolean): Promise<void>;
export declare function getChangePasswordChannels<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>>(params: {
userId: string;

View File

@ -11,7 +11,7 @@ async function mergeUser(params, context, innerLogic) {
if (!innerLogic && !context.isRoot()) {
throw new types_1.OakUserUnpermittedException('不允许执行mergeUser操作');
}
const { from, to } = params;
const { from, to, mergeMobile, mergeEmail, mergeWechatUser } = params;
(0, assert_1.assert)(from);
(0, assert_1.assert)(to);
(0, assert_1.assert)(from !== to, '不能merge到相同user');
@ -81,6 +81,42 @@ async function mergeUser(params, context, innerLogic) {
],
},
}, {});
if (mergeEmail) {
await context.operate('email', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
if (mergeMobile) {
await context.operate('mobile', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
if (mergeWechatUser) {
await context.operate('wechatUser', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
}
exports.mergeUser = mergeUser;
async function getChangePasswordChannels(params, context, innerLogic) {

View File

@ -1,2 +1,2 @@
declare const _default: (import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "account", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>>)[];
declare const _default: (import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "account", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").RuntimeCxt> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>> | import("oak-domain").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BackendRuntimeContext<import("../oak-app-domain").EntityDict>>)[];
export default _default;

View File

@ -195,6 +195,11 @@ async function dealWithUserState(
}
}
function autoMergeUser<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>>(context: Cxt) {
const { system } = context.getApplication()!;
return !!system!.config!.App.mergeUserDirectly;
}
/**
* user的不同情况
* @param env
@ -237,33 +242,29 @@ async function setUpTokenAndUser<
if (currentToken.userId === user.id) {
return currentToken.id;
}
await mergeUser<ED, Cxt>(
{ from: user.id!, to: currentToken.userId! },
context,
true
);
return currentToken.id;
const autoMerge = autoMergeUser<ED, Cxt>(context);
if (autoMerge) {
await mergeUser<ED, Cxt>(
{ from: user.id!, to: currentToken.userId!, mergeMobile: true, mergeWechatUser: true, mergeEmail: true },
context,
true
);
return currentToken.id;
}
throw await makeDistinguishException<ED, Cxt>(user.id!, context);
}
case 'shadow': {
assert(currentToken.userId !== user.id);
await mergeUser<ED, Cxt>(
{ from: user.id!, to: currentToken.userId! },
context,
true
);
// await context.operate(
// 'user',
// {
// id: await generateNewIdAsync(),
// action: 'activate',
// data: {},
// filter: {
// id: user.id!,
// },
// },
// { dontCollect: true }
// );
return currentToken.id;
const autoMerge = autoMergeUser<ED, Cxt>(context);
if (autoMerge) {
await mergeUser<ED, Cxt>(
{ from: user.id!, to: currentToken.userId!, mergeMobile: true, mergeWechatUser: true, mergeEmail: true },
context,
true
);
return currentToken.id;
}
throw await makeDistinguishException<ED, Cxt>(user.id!, context);
}
case 'disabled': {
throw new OakUserDisabledException();
@ -273,16 +274,20 @@ async function setUpTokenAndUser<
if (user.refId === currentToken.userId) {
return currentToken.id;
}
// 说明一个用户被其他用户merge了现在还是暂时先merge后面再说
console.warn(
`用户${user.id}已经是merged状态「${user.refId}再次被merged到「${currentToken.userId}]」`
);
await mergeUser<ED, Cxt>(
{ from: user.id!, to: currentToken.userId! },
context,
true
);
return currentToken.id;
const autoMerge = autoMergeUser<ED, Cxt>(context);
if (autoMerge) {
// 说明一个用户被其他用户merge了现在还是暂时先merge后面再说
console.warn(
`用户${user.id}已经是merged状态「${user.refId}再次被merged到「${currentToken.userId}]」`
);
await mergeUser<ED, Cxt>(
{ from: user.id!, to: currentToken.userId!, mergeMobile: true, mergeWechatUser: true, mergeEmail: true },
context,
true
);
return currentToken.id;
}
throw await makeDistinguishException<ED, Cxt>(user.id!, context);
}
default: {
assert(false, `不能理解的user状态「${userState}`);

View File

@ -7,11 +7,19 @@ import { encryptPasswordSha1 } from '../utils/password';
import { assert } from 'oak-domain/lib/utils/assert';
import dayjs from 'dayjs';
export async function mergeUser<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>>(params: { from: string, to: string }, context: Cxt, innerLogic?: boolean) {
export async function mergeUser<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>>(
params: {
from: string,
to: string,
mergeMobile?: true,
mergeEmail?: true,
mergeWechatUser?: true,
}, context: Cxt, innerLogic?: boolean
) {
if (!innerLogic && !context.isRoot()) {
throw new OakUserUnpermittedException('不允许执行mergeUser操作');
}
const { from, to } = params;
const { from, to, mergeMobile, mergeEmail, mergeWechatUser } = params;
assert(from);
assert(to);
assert(from !== to, '不能merge到相同user');
@ -83,6 +91,43 @@ export async function mergeUser<ED extends EntityDict & BaseEntityDict, Cxt exte
],
},
}, {});
if (mergeEmail) {
await context.operate('email', {
id: await generateNewIdAsync(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
if (mergeMobile) {
await context.operate('mobile', {
id: await generateNewIdAsync(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
if (mergeWechatUser) {
await context.operate('wechatUser', {
id: await generateNewIdAsync(),
action: 'update',
data: {
userId: to,
},
filter: {
userId: from,
}
}, { dontCollect: true });
}
}
export async function getChangePasswordChannels<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>>(params: { userId: string }, context: Cxt, innerLogic?: boolean) {