更正了一堆userEntityGrant相关的bug

This commit is contained in:
Xu Chang 2025-10-10 19:17:51 +08:00
parent 0e7db712bb
commit 6c8efa9d00
21 changed files with 211 additions and 617 deletions

View File

@ -1,6 +1,7 @@
import { OakInputIllegalException, } from 'oak-domain/lib/types'; import { OakInputIllegalException, } from 'oak-domain/lib/types';
import { assert } from 'oak-domain/lib/utils/assert'; import { assert } from 'oak-domain/lib/utils/assert';
import { generateNewId } from 'oak-domain/lib/utils/uuid'; import { generateNewId } from 'oak-domain/lib/utils/uuid';
import { pipeline } from 'oak-domain/lib/utils/executor';
const checkers = [ const checkers = [
{ {
type: 'data', type: 'data',
@ -40,20 +41,8 @@ const checkers = [
const { userEntityClaim$ueg } = data; const { userEntityClaim$ueg } = data;
assert(filter.id); assert(filter.id);
assert(userEntityClaim$ueg instanceof Array); assert(userEntityClaim$ueg instanceof Array);
const result = context.select('userEntityGrant', {
data: {
id: 1,
relationEntity: 1,
multiple: 1,
},
filter,
}, option);
const dealInner = (userEntityGrant) => { const dealInner = (userEntityGrant) => {
const { relationEntity, multiple } = userEntityGrant; const { relationEntity } = userEntityGrant;
if (!multiple) {
userEntityGrant.expired = true;
userEntityGrant.expiresAt = Date.now();
}
userEntityClaim$ueg.forEach((uec) => { userEntityClaim$ueg.forEach((uec) => {
const { action, data } = uec; const { action, data } = uec;
assert(action === 'create'); assert(action === 'create');
@ -74,10 +63,14 @@ const checkers = [
}); });
return userEntityClaim$ueg.length; return userEntityClaim$ueg.length;
}; };
if (result instanceof Promise) { return pipeline(() => context.select('userEntityGrant', {
return result.then(([ueg]) => dealInner(ueg)); data: {
} id: 1,
return dealInner(result[0]); relationEntity: 1,
multiple: 1,
},
filter,
}, option), ([ueg]) => dealInner(ueg));
} }
} }
]; ];

View File

@ -1,7 +1,7 @@
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "article", true, { declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "article", true, {
articleMenuId: string | undefined; articleMenuId: string | undefined;
onChildEditArticleChange: (data: string) => void; onChildEditArticleChange: (data: string) => void;
show: "preview" | "edit" | "doc"; show: "edit" | "doc" | "preview";
getBreadcrumbItemsByParent: (breadcrumbItems: string[]) => void; getBreadcrumbItemsByParent: (breadcrumbItems: string[]) => void;
breadcrumbItems: string[]; breadcrumbItems: string[];
drawerOpen: boolean; drawerOpen: boolean;

View File

@ -2,7 +2,7 @@ declare const _default: (props: import("oak-frontend-base").ReactComponentProps<
onRemove: () => void; onRemove: () => void;
onUpdateName: (name: string) => Promise<void>; onUpdateName: (name: string) => Promise<void>;
onChildEditArticleChange: (data: string) => void; onChildEditArticleChange: (data: string) => void;
show: "preview" | "edit" | "doc"; show: "edit" | "doc" | "preview";
getBreadcrumbItemsByParent: (breadcrumbItems: string[]) => void; getBreadcrumbItemsByParent: (breadcrumbItems: string[]) => void;
breadItems: string[]; breadItems: string[];
drawerOpen: boolean; drawerOpen: boolean;

View File

@ -4,7 +4,7 @@ declare const _default: (props: import("oak-frontend-base").ReactComponentProps<
entityId: string; entityId: string;
parentId: string | undefined; parentId: string | undefined;
onGrandChildEditArticleChange: (data: string) => void; onGrandChildEditArticleChange: (data: string) => void;
show: "preview" | "edit" | "doc"; show: "edit" | "doc" | "preview";
articleMenuId: string; articleMenuId: string;
articleId: string; articleId: string;
getBreadcrumbItems: (breadcrumbItems: string[]) => void; getBreadcrumbItems: (breadcrumbItems: string[]) => void;

View File

@ -1,7 +1,7 @@
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "articleMenu", true, { declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "articleMenu", true, {
entity: string; entity: string;
entityId: string; entityId: string;
show: "preview" | "edit" | "doc"; show: "edit" | "doc" | "preview";
articleMenuId: string; articleMenuId: string;
articleId: string; articleId: string;
tocPosition: "none" | "left" | "right"; tocPosition: "none" | "left" | "right";

View File

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

View File

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

View File

@ -15,7 +15,7 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
type?: ButtonProps['type'] | AmButtonProps['type']; type?: ButtonProps['type'] | AmButtonProps['type'];
executeText?: string | undefined; executeText?: string | undefined;
buttonProps?: (ButtonProps & { buttonProps?: (ButtonProps & {
color?: "default" | "success" | "warning" | "primary" | "danger" | undefined; color?: "default" | "primary" | "success" | "warning" | "danger" | undefined;
fill?: "none" | "solid" | "outline" | undefined; fill?: "none" | "solid" | "outline" | undefined;
size?: "small" | "large" | "middle" | "mini" | undefined; size?: "small" | "large" | "middle" | "mini" | undefined;
block?: boolean | undefined; block?: boolean | undefined;

View File

@ -139,9 +139,7 @@ export default OakComponent({
return; return;
} }
} }
this.navigateTo({ process.env.NODE_ENV === 'development' && console.warn('没有正确处理领取后的行为');
url: '/',
});
} }
} }
}); });

View File

@ -12,8 +12,8 @@
</l-button> </l-button>
</view> </view>
</view> </view>
</block> </block>
<block wx:else> <block wx:else>
<view class="list-item"> <view class="list-item">
<view class="label">{{t('userEntityGrant:attr.relationIds')}}</view> <view class="label">{{t('userEntityGrant:attr.relationIds')}}</view>
<view class="value"> <view class="value">

View File

@ -1,6 +1,6 @@
import { EntityDict } from '../../../oak-app-domain'; import { EntityDict } from '../../../oak-app-domain';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, keyof EntityDict, false, { declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, keyof EntityDict, false, {
type: "bind" | "login"; type: "login" | "bind";
url: string; url: string;
size: undefined; size: undefined;
}>) => React.ReactElement; }>) => React.ReactElement;

View File

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

View File

@ -14,7 +14,7 @@ export declare function createToDo<ED extends EntityDict & BaseEntityDict, T ext
redirectTo: EntityDict['toDo']['OpSchema']['redirectTo']; redirectTo: EntityDict['toDo']['OpSchema']['redirectTo'];
entity: any; entity: any;
entityId: string; entityId: string;
}, userIds?: string[]): Promise<1 | 0>; }, userIds?: string[]): Promise<0 | 1>;
/** /**
* todo例程entity对象上进行action操作时filtertodo完成 * todo例程entity对象上进行action操作时filtertodo完成
* entity的action的后trigger中调用 * entity的action的后trigger中调用

View File

@ -47,181 +47,54 @@ const triggers = [
return 0; return 0;
}, },
}, },
/* {
name: '当userEntityGrant准备确认时附上被授权者id',
entity: 'userEntityGrant',
action: 'confirm',
when: 'before',
fn: async ({ operation }, context, params) => {
const { data, filter } = operation;
const { userId } = context.getToken()!;
const closeRootMode = context.openRootMode();
const result = await context.select(
'userEntityGrant',
{
data: {
id: 1,
entity: 1,
entityId: 1,
relationId: 1,
number: 1,
confirmed: 1,
},
filter: {
id: filter!.id,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
const { number, confirmed } = result[0];
if (confirmed! >= number!) {
throw new OakUserException(`超出分享上限人数${number}`);
}
Object.assign(data, {
confirmed: confirmed! + 1,
});
if (number === 1) {
// 单次分享 附上接收者id
Object.assign(data, {
granteeId: userId,
});
}
closeRootMode();
return 0;
},
} as UpdateTrigger<EntityDict, 'userEntityGrant', BRC>,
{
name: '当userEntityGrant被确认时生成user和entity关系',
entity: 'userEntityGrant',
action: 'confirm',
when: 'after',
fn: async ({ operation }, context, option) => {
const { data, filter } = operation;
const { userId } = context.getToken()!;
const closeRootMode = context.openRootMode();
const [userEntityGrant] = await context.select(
'userEntityGrant',
{
data: {
id: 1,
entity: 1,
entityId: 1,
relationId: 1,
granterId: 1,
type: 1,
},
filter: {
id: filter!.id,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
const { entity, entityId, relationId, granterId, type } =
userEntityGrant;
const result2 = await context.select(
'userRelation',
{
data: {
id: 1,
userId: 1,
relationId: 1,
},
filter: {
userId: userId!,
relationId,
entity,
entityId,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
if (result2.length) {
const e = new OakRowInconsistencyException<EntityDict>('已领取该权限');
e.addData('userRelation', result2, context.getSchema());
closeRootMode();
throw e;
} else {
try {
await context.operate(
'userRelation',
{
id: await generateNewIdAsync(),
action: 'create',
data: {
id: await generateNewIdAsync(),
userId,
relationId,
entity,
entityId,
},
},
option
);
// todo type是转让的话 需要回收授权者的关系
if (type === 'transfer') {
await context.operate(
'userRelation',
{
id: await generateNewIdAsync(),
action: 'remove',
data: {},
filter: {
relationId,
userId: granterId,
entity,
entityId,
},
},
option
);
}
} catch (err) {
closeRootMode();
throw err;
}
closeRootMode();
return 1;
}
},
} as UpdateTrigger<EntityDict, 'userEntityGrant', BRC>, */
{ {
name: '当userEntityGrant过期时使其相关的wechatQrCode也过期', name: '当userEntityGrant过期时使其相关的wechatQrCode也过期',
entity: 'userEntityGrant', entity: 'userEntityGrant',
action: 'update', action: ['update', 'claim'],
check: (operation) => { check: (operation) => {
const { data } = operation; const { data } = operation;
return !!data.expired; return !!data.expired;
}, },
priority: 32,
when: 'before', when: 'before',
fn: async ({ operation }, context) => { fn: async ({ operation }, context) => {
const { data, filter } = operation; const { data, filter } = operation;
await context.operate('wechatQrCode', { data.wechatQrCode$entity = [
id: await generateNewIdAsync(), {
action: 'update', id: await generateNewIdAsync(),
data: { action: 'update',
expired: true, data: {
}, expired: true,
filter: { expiresAt: Date.now(),
userEntityGrant: filter, },
}, }
}, {}); ];
return 1; return 1;
}, },
}, },
{
name: '当claim一个userEntityGrant时如果是单次的则将之过期',
entity: 'userEntityGrant',
action: 'claim',
when: 'before',
priority: 13,
fn: async ({ operation }, context) => {
const { data, filter } = operation;
assert(typeof filter.id === 'string');
const [userEntityGrant] = await context.select('userEntityGrant', {
data: {
id: 1,
multiple: 1,
},
filter
}, { dontCollect: true });
if (!userEntityGrant.multiple) {
data.expired = true;
data.expiresAt = Date.now();
return 1;
}
return 0;
}
}
]; ];
export default triggers; export default triggers;

View File

@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const types_1 = require("oak-domain/lib/types"); const types_1 = require("oak-domain/lib/types");
const assert_1 = require("oak-domain/lib/utils/assert"); const assert_1 = require("oak-domain/lib/utils/assert");
const uuid_1 = require("oak-domain/lib/utils/uuid"); const uuid_1 = require("oak-domain/lib/utils/uuid");
const executor_1 = require("oak-domain/lib/utils/executor");
const checkers = [ const checkers = [
{ {
type: 'data', type: 'data',
@ -42,20 +43,8 @@ const checkers = [
const { userEntityClaim$ueg } = data; const { userEntityClaim$ueg } = data;
(0, assert_1.assert)(filter.id); (0, assert_1.assert)(filter.id);
(0, assert_1.assert)(userEntityClaim$ueg instanceof Array); (0, assert_1.assert)(userEntityClaim$ueg instanceof Array);
const result = context.select('userEntityGrant', {
data: {
id: 1,
relationEntity: 1,
multiple: 1,
},
filter,
}, option);
const dealInner = (userEntityGrant) => { const dealInner = (userEntityGrant) => {
const { relationEntity, multiple } = userEntityGrant; const { relationEntity } = userEntityGrant;
if (!multiple) {
userEntityGrant.expired = true;
userEntityGrant.expiresAt = Date.now();
}
userEntityClaim$ueg.forEach((uec) => { userEntityClaim$ueg.forEach((uec) => {
const { action, data } = uec; const { action, data } = uec;
(0, assert_1.assert)(action === 'create'); (0, assert_1.assert)(action === 'create');
@ -76,10 +65,14 @@ const checkers = [
}); });
return userEntityClaim$ueg.length; return userEntityClaim$ueg.length;
}; };
if (result instanceof Promise) { return (0, executor_1.pipeline)(() => context.select('userEntityGrant', {
return result.then(([ueg]) => dealInner(ueg)); data: {
} id: 1,
return dealInner(result[0]); relationEntity: 1,
multiple: 1,
},
filter,
}, option), ([ueg]) => dealInner(ueg));
} }
} }
]; ];

View File

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

View File

@ -14,7 +14,7 @@ export declare function createToDo<ED extends EntityDict & BaseEntityDict, T ext
redirectTo: EntityDict['toDo']['OpSchema']['redirectTo']; redirectTo: EntityDict['toDo']['OpSchema']['redirectTo'];
entity: any; entity: any;
entityId: string; entityId: string;
}, userIds?: string[]): Promise<1 | 0>; }, userIds?: string[]): Promise<0 | 1>;
/** /**
* todo例程entity对象上进行action操作时filtertodo完成 * todo例程entity对象上进行action操作时filtertodo完成
* entity的action的后trigger中调用 * entity的action的后trigger中调用

View File

@ -49,181 +49,54 @@ const triggers = [
return 0; return 0;
}, },
}, },
/* {
name: '当userEntityGrant准备确认时附上被授权者id',
entity: 'userEntityGrant',
action: 'confirm',
when: 'before',
fn: async ({ operation }, context, params) => {
const { data, filter } = operation;
const { userId } = context.getToken()!;
const closeRootMode = context.openRootMode();
const result = await context.select(
'userEntityGrant',
{
data: {
id: 1,
entity: 1,
entityId: 1,
relationId: 1,
number: 1,
confirmed: 1,
},
filter: {
id: filter!.id,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
const { number, confirmed } = result[0];
if (confirmed! >= number!) {
throw new OakUserException(`超出分享上限人数${number}`);
}
Object.assign(data, {
confirmed: confirmed! + 1,
});
if (number === 1) {
// 单次分享 附上接收者id
Object.assign(data, {
granteeId: userId,
});
}
closeRootMode();
return 0;
},
} as UpdateTrigger<EntityDict, 'userEntityGrant', BRC>,
{
name: '当userEntityGrant被确认时生成user和entity关系',
entity: 'userEntityGrant',
action: 'confirm',
when: 'after',
fn: async ({ operation }, context, option) => {
const { data, filter } = operation;
const { userId } = context.getToken()!;
const closeRootMode = context.openRootMode();
const [userEntityGrant] = await context.select(
'userEntityGrant',
{
data: {
id: 1,
entity: 1,
entityId: 1,
relationId: 1,
granterId: 1,
type: 1,
},
filter: {
id: filter!.id,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
const { entity, entityId, relationId, granterId, type } =
userEntityGrant;
const result2 = await context.select(
'userRelation',
{
data: {
id: 1,
userId: 1,
relationId: 1,
},
filter: {
userId: userId!,
relationId,
entity,
entityId,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
if (result2.length) {
const e = new OakRowInconsistencyException<EntityDict>('已领取该权限');
e.addData('userRelation', result2, context.getSchema());
closeRootMode();
throw e;
} else {
try {
await context.operate(
'userRelation',
{
id: await generateNewIdAsync(),
action: 'create',
data: {
id: await generateNewIdAsync(),
userId,
relationId,
entity,
entityId,
},
},
option
);
// todo type是转让的话 需要回收授权者的关系
if (type === 'transfer') {
await context.operate(
'userRelation',
{
id: await generateNewIdAsync(),
action: 'remove',
data: {},
filter: {
relationId,
userId: granterId,
entity,
entityId,
},
},
option
);
}
} catch (err) {
closeRootMode();
throw err;
}
closeRootMode();
return 1;
}
},
} as UpdateTrigger<EntityDict, 'userEntityGrant', BRC>, */
{ {
name: '当userEntityGrant过期时使其相关的wechatQrCode也过期', name: '当userEntityGrant过期时使其相关的wechatQrCode也过期',
entity: 'userEntityGrant', entity: 'userEntityGrant',
action: 'update', action: ['update', 'claim'],
check: (operation) => { check: (operation) => {
const { data } = operation; const { data } = operation;
return !!data.expired; return !!data.expired;
}, },
priority: 32,
when: 'before', when: 'before',
fn: async ({ operation }, context) => { fn: async ({ operation }, context) => {
const { data, filter } = operation; const { data, filter } = operation;
await context.operate('wechatQrCode', { data.wechatQrCode$entity = [
id: await (0, uuid_1.generateNewIdAsync)(), {
action: 'update', id: await (0, uuid_1.generateNewIdAsync)(),
data: { action: 'update',
expired: true, data: {
}, expired: true,
filter: { expiresAt: Date.now(),
userEntityGrant: filter, },
}, }
}, {}); ];
return 1; return 1;
}, },
}, },
{
name: '当claim一个userEntityGrant时如果是单次的则将之过期',
entity: 'userEntityGrant',
action: 'claim',
when: 'before',
priority: 13,
fn: async ({ operation }, context) => {
const { data, filter } = operation;
(0, assert_1.assert)(typeof filter.id === 'string');
const [userEntityGrant] = await context.select('userEntityGrant', {
data: {
id: 1,
multiple: 1,
},
filter
}, { dontCollect: true });
if (!userEntityGrant.multiple) {
data.expired = true;
data.expiresAt = Date.now();
return 1;
}
return 0;
}
}
]; ];
exports.default = triggers; exports.default = triggers;

View File

@ -6,103 +6,98 @@ import { checkAttributesNotNull } from 'oak-domain/lib/utils/validator';
import { RuntimeCxt } from '../types/RuntimeCxt'; import { RuntimeCxt } from '../types/RuntimeCxt';
import { assert } from 'oak-domain/lib/utils/assert'; import { assert } from 'oak-domain/lib/utils/assert';
import { generateNewId } from 'oak-domain/lib/utils/uuid'; import { generateNewId } from 'oak-domain/lib/utils/uuid';
import { pipeline } from 'oak-domain/lib/utils/executor';
import { OpSchema } from '../oak-app-domain/ActionAuth/_baseSchema';
const checkers: Checker< const checkers: Checker<
EntityDict, EntityDict,
'userEntityGrant', 'userEntityGrant',
RuntimeCxt<EntityDict> RuntimeCxt<EntityDict>
>[] = [ >[] = [
{ {
type: 'data', type: 'data',
action: 'create', action: 'create',
entity: 'userEntityGrant', entity: 'userEntityGrant',
checker: (data) => { checker: (data) => {
if (data instanceof Array) { if (data instanceof Array) {
data.forEach((ele) => { data.forEach((ele) => {
if (!ele.relationIds || ele.relationIds!.length === 0) { if (!ele.relationIds || ele.relationIds!.length === 0) {
throw new OakInputIllegalException(
'userEntityGrant',
['relationIds'],
'至少应选择一个关系'
);
}
});
} else {
if (!data.relationIds || data.relationIds!.length === 0) {
throw new OakInputIllegalException( throw new OakInputIllegalException(
'userEntityGrant', 'userEntityGrant',
['relationIds'], ['relationIds'],
'至少应选择一个关系' '至少应选择一个关系'
); );
} }
});
} else {
if (!data.relationIds || data.relationIds!.length === 0) {
throw new OakInputIllegalException(
'userEntityGrant',
['relationIds'],
'至少应选择一个关系'
);
} }
} },
}, },
}, {
{ type: 'row',
type: 'row', entity: 'userEntityGrant',
entity: 'userEntityGrant', action: 'claim',
action: 'claim', filter: {
filter: { expired: false,
expired: false, },
}, },
}, {
{ type: 'logical',
type: 'logical', entity: 'userEntityGrant',
entity:'userEntityGrant', action: 'claim',
action: 'claim', checker: (operation, context, option) => {
checker: (operation, context, option) => { const { data, filter } = operation as EntityDict['userEntityGrant']['Update'];
const { data, filter } = operation as EntityDict['userEntityGrant']['Update']; // assert(Object.keys(data).length === 1 && data.hasOwnProperty('userEntityClaim$ueg'));
// assert(Object.keys(data).length === 1 && data.hasOwnProperty('userEntityClaim$ueg')); assert(data.hasOwnProperty('userEntityClaim$ueg'));
assert(data.hasOwnProperty('userEntityClaim$ueg')); const { userEntityClaim$ueg } = data;
const { userEntityClaim$ueg } = data; assert(filter!.id);
assert(filter!.id); assert(userEntityClaim$ueg instanceof Array);
assert(userEntityClaim$ueg instanceof Array);
const result = context.select('userEntityGrant', { const dealInner = (userEntityGrant: Partial<EntityDict['userEntityGrant']['OpSchema']>) => {
data: { const { relationEntity } = userEntityGrant;
id: 1, userEntityClaim$ueg.forEach(
relationEntity: 1, (uec) => {
multiple: 1, const { action, data } = uec as EntityDict['userEntityClaim']['CreateSingle'];
}, assert(action === 'create');
filter, const { userId, relationId, claimEntityId } = data;
}, option); Object.assign(data, {
const dealInner = (userEntityGrant: Partial<EntityDict['userEntityGrant']['OpSchema']>) => { userRelation: {
const { relationEntity, multiple } = userEntityGrant;
if (!multiple) {
userEntityGrant.expired = true;
userEntityGrant.expiresAt = Date.now();
}
userEntityClaim$ueg.forEach(
(uec) => {
const { action, data } = uec as EntityDict['userEntityClaim']['CreateSingle'];
assert(action === 'create');
const { userId, relationId, claimEntityId } = data;
Object.assign(data, {
userRelation: {
id: generateNewId(),
action: 'create',
data: {
id: generateNewId(), id: generateNewId(),
userId, action: 'create',
relationId, data: {
entityId: claimEntityId, id: generateNewId(),
entity: relationEntity, userId,
relationId,
entityId: claimEntityId,
entity: relationEntity,
}
} }
} });
}); }
} );
);
return userEntityClaim$ueg.length; return userEntityClaim$ueg.length;
} }
if (result instanceof Promise) { return pipeline(
return result.then( () => context.select('userEntityGrant', {
([ueg]) => dealInner(ueg) data: {
id: 1,
relationEntity: 1,
multiple: 1,
},
filter,
}, option),
([ueg]: [EntityDict['userEntityGrant']['OpSchema']]) => dealInner(ueg)
); );
} }
return dealInner(result[0]);
} }
} ];
];
export default checkers; export default checkers;

View File

@ -176,9 +176,8 @@ export default OakComponent({
return; return;
} }
} }
this.navigateTo({
url: '/', process.env.NODE_ENV === 'development' && console.warn('没有正确处理领取后的行为');
});
} }
} }
}); });

View File

@ -56,186 +56,56 @@ const triggers: Trigger<EntityDict, 'userEntityGrant', BRC<EntityDict>>[] = [
return 0; return 0;
}, },
} as CreateTrigger<EntityDict, 'userEntityGrant', BRC<EntityDict>>, } as CreateTrigger<EntityDict, 'userEntityGrant', BRC<EntityDict>>,
/* {
name: '当userEntityGrant准备确认时附上被授权者id',
entity: 'userEntityGrant',
action: 'confirm',
when: 'before',
fn: async ({ operation }, context, params) => {
const { data, filter } = operation;
const { userId } = context.getToken()!;
const closeRootMode = context.openRootMode();
const result = await context.select(
'userEntityGrant',
{
data: {
id: 1,
entity: 1,
entityId: 1,
relationId: 1,
number: 1,
confirmed: 1,
},
filter: {
id: filter!.id,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
const { number, confirmed } = result[0];
if (confirmed! >= number!) {
throw new OakUserException(`超出分享上限人数${number}`);
}
Object.assign(data, {
confirmed: confirmed! + 1,
});
if (number === 1) {
// 单次分享 附上接收者id
Object.assign(data, {
granteeId: userId,
});
}
closeRootMode();
return 0;
},
} as UpdateTrigger<EntityDict, 'userEntityGrant', BRC>,
{
name: '当userEntityGrant被确认时生成user和entity关系',
entity: 'userEntityGrant',
action: 'confirm',
when: 'after',
fn: async ({ operation }, context, option) => {
const { data, filter } = operation;
const { userId } = context.getToken()!;
const closeRootMode = context.openRootMode();
const [userEntityGrant] = await context.select(
'userEntityGrant',
{
data: {
id: 1,
entity: 1,
entityId: 1,
relationId: 1,
granterId: 1,
type: 1,
},
filter: {
id: filter!.id,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
const { entity, entityId, relationId, granterId, type } =
userEntityGrant;
const result2 = await context.select(
'userRelation',
{
data: {
id: 1,
userId: 1,
relationId: 1,
},
filter: {
userId: userId!,
relationId,
entity,
entityId,
},
indexFrom: 0,
count: 1,
},
{
dontCollect: true,
}
);
if (result2.length) {
const e = new OakRowInconsistencyException<EntityDict>('已领取该权限');
e.addData('userRelation', result2, context.getSchema());
closeRootMode();
throw e;
} else {
try {
await context.operate(
'userRelation',
{
id: await generateNewIdAsync(),
action: 'create',
data: {
id: await generateNewIdAsync(),
userId,
relationId,
entity,
entityId,
},
},
option
);
// todo type是转让的话 需要回收授权者的关系
if (type === 'transfer') {
await context.operate(
'userRelation',
{
id: await generateNewIdAsync(),
action: 'remove',
data: {},
filter: {
relationId,
userId: granterId,
entity,
entityId,
},
},
option
);
}
} catch (err) {
closeRootMode();
throw err;
}
closeRootMode();
return 1;
}
},
} as UpdateTrigger<EntityDict, 'userEntityGrant', BRC>, */
{ {
name: '当userEntityGrant过期时使其相关的wechatQrCode也过期', name: '当userEntityGrant过期时使其相关的wechatQrCode也过期',
entity: 'userEntityGrant', entity: 'userEntityGrant',
action: 'update', action: ['update', 'claim'],
check: (operation) => { check: (operation) => {
const { data } = operation; const { data } = operation;
return !!data.expired; return !!data.expired;
}, },
priority: 32,
when: 'before', when: 'before',
fn: async ({ operation }, context) => { fn: async ({ operation }, context) => {
const { data, filter } = operation; const { data, filter } = operation;
await context.operate( data.wechatQrCode$entity = [
'wechatQrCode',
{ {
id: await generateNewIdAsync(), id: await generateNewIdAsync(),
action: 'update', action: 'update',
data: { data: {
expired: true, expired: true,
expiresAt: Date.now(),
}, },
filter: { }
userEntityGrant: filter, ];
},
},
{}
);
return 1; return 1;
}, },
} as UpdateTrigger<EntityDict, 'userEntityGrant', BRC<EntityDict>>, } as UpdateTrigger<EntityDict, 'userEntityGrant', BRC<EntityDict>>,
{
name: '当claim一个userEntityGrant时如果是单次的则将之过期',
entity: 'userEntityGrant',
action: 'claim',
when: 'before',
priority: 13,
fn: async ({ operation }, context) => {
const { data, filter } = operation as EntityDict['userEntityGrant']['Update'];
assert(typeof filter!.id === 'string');
const [userEntityGrant] = await context.select('userEntityGrant', {
data: {
id: 1,
multiple: 1,
},
filter
}, { dontCollect: true });
if (!userEntityGrant.multiple) {
data.expired = true;
data.expiresAt = Date.now();
return 1;
}
return 0;
}
}
]; ];
export default triggers; export default triggers;