编译的中间文件

This commit is contained in:
Xu Chang 2022-05-10 15:01:45 +08:00
parent 73bd233099
commit 60aa0ad725
43 changed files with 127 additions and 809 deletions

View File

@ -1,24 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const actionDef_1 = require("oak-domain/lib/store/actionDef");
const checkers = [
{
type: 'data',
action: 'create',
action: 'remove',
entity: 'user',
checker: async ({ operation }) => {
/* const { action, data } = operation;
if (data instanceof Array) {
data.forEach(
ele => {
checkAttributesNotNull(ele, ['nickname']);
}
);
}
else {
checkAttributesNotNull(data, ['nickname']);
} */
checker: async ({ operation }, context) => {
const { filter } = operation;
await (0, actionDef_1.checkFilterContains)('user', context.rowStore.getSchema(), {
idState: 'shadow',
}, context, filter);
return 0;
},
},
{
type: 'user',
action: 'play',
}
];
exports.default = checkers;

View File

@ -53,6 +53,10 @@ export abstract class GeneralRuntimeContext<ED extends EntityDict> extends Unive
}
}
async getTokenValue() {
return await this.getTokenFn();
}
getScene() {
return this.scene;
}

View File

@ -1,7 +1,7 @@
import { isMobile } from 'oak-domain/lib/utils/validator';
import { OakInputIllegalException, Checker } from "oak-domain/lib/types";
import { EntityDict } from 'oak-app-domain';
import { checkAttributesNotNull } from '../utils/check';
import { checkAttributesNotNull } from 'oak-domain/lib/utils/validator';
import { GeneralRuntimeContext } from '../RuntimeContext';
const checkers: Checker<EntityDict, 'address', GeneralRuntimeContext<EntityDict>> [] = [

View File

@ -3,7 +3,8 @@ import { EntityDict } from 'oak-app-domain';
import { GeneralRuntimeContext } from '../RuntimeContext';
import { OakUnloggedInException } from "../types/Exceptions";
import { assign } from "lodash";
import { combineFilters } from "oak-domain/lib/store/filter";
import { addFilterSegment, combineFilters } from "oak-domain/lib/store/filter";
import { checkIsRoot } from "../utils/check";
const checkers: Checker<EntityDict, 'token', GeneralRuntimeContext<EntityDict>> [] = [
{
@ -31,7 +32,22 @@ const checkers: Checker<EntityDict, 'token', GeneralRuntimeContext<EntityDict>>
return 0;
}
// 对获取token的权限进行精细化控制除了root
throw new OakUserUnpermittedException();
if (filter && filter.id === await context.getTokenValue()) {
return 0;
}
const isRoot = await checkIsRoot(context);
if (!isRoot) {
// 不是root只能访问自己的token
if (!filter) {
throw new OakUserUnpermittedException();
}
assign(operation, {
filter: addFilterSegment(filter, {
id: await context.getTokenValue(),
})
});
}
return 0;
},
}
];

View File

@ -1,26 +1,38 @@
import { isMobile } from 'oak-domain/lib/utils/validator';
import { OakInputIllegalException, Checker } from "oak-domain/lib/types";
import { checkFilterContains } from 'oak-domain/lib/store/actionDef';
import { OakInputIllegalException, Checker, OakUserUnpermittedException, OakRowInconsistencyException } from "oak-domain/lib/types";
import { EntityDict } from 'oak-app-domain';
import { checkAttributesNotNull } from '../utils/check';
import { GeneralRuntimeContext } from '../RuntimeContext';
import { ROOT_ROLE_ID } from '../constants';
import { assign } from 'lodash';
import { checkIsRoot } from '../utils/check';
const checkers: Checker<EntityDict, 'user', GeneralRuntimeContext<EntityDict>> [] = [
{
type: 'data',
action: 'create',
action: 'remove',
entity: 'user',
checker: async ({ operation }) => {
/* const { action, data } = operation;
if (data instanceof Array) {
data.forEach(
ele => {
checkAttributesNotNull(ele, ['nickname']);
}
);
checker: async ({ operation }, context) => {
const { filter } = operation;
await checkFilterContains('user', context.rowStore.getSchema(), {
idState: 'shadow',
}, context, filter);
return 0;
},
},
{
type: 'user',
action: 'play',
entity: 'user',
checker: async ({ operation }, context) => {
const isRoot = await checkIsRoot(context);
if (!isRoot) {
throw new OakUserUnpermittedException();
}
const token = await context.getToken();
const { userId } = token!;
if (userId === operation.filter!.id) {
throw new OakRowInconsistencyException();
}
else {
checkAttributesNotNull(data, ['nickname']);
} */
return 0;
},
}

View File

@ -40,7 +40,9 @@ const UserActionDef: ActionDef<UserAction, UserState> = {
},
};
type Action = UserAction | IdAction;
type CascadeAction = 'play';
type Action = UserAction | IdAction | CascadeAction;
const indexes: Index<Schema>[] = [
{

View File

@ -67,6 +67,27 @@ const triggers: Trigger<EntityDict, 'user', GeneralRuntimeContext<EntityDict>>[]
return 0;
}
},
{
name: '当扮演某个用户时切换当前用户的token中的userId',
entity: 'user',
action: 'play',
when: 'after',
fn: async ({ operation }, context, params) => {
const { filter } = operation;
assert (filter!.id);
const { id } = (await context.getToken())!;
await context.rowStore.operate('token', {
action: 'update',
data: {
userId: filter!.id,
},
filter: {
id,
}
}, context);
return 1;
}
}
];
export default triggers;

View File

@ -1,28 +1,23 @@
import { OakInputIllegalException } from "oak-domain/lib/types";
import { EntityDict } from "oak-app-domain";
import { ROOT_ROLE_ID } from "../constants";
import { GeneralRuntimeContext } from "../RuntimeContext";
export function checkAttributesNotNull<T extends Record<string, any>>(data: T, attributes: Array<keyof T>, allowEmpty?: true) {
const attrs = attributes.filter(
(attr) => {
if (data[attr] === null || data[attr] === '') {
return true;
}
if (!allowEmpty && !data.hasOwnProperty(attr)) {
return true;
}
}
) as string[];
if (attrs.length > 0) {
throw new OakInputIllegalException(attrs, '属性不能为空');
export async function checkIsRoot(context: GeneralRuntimeContext<EntityDict>) {
const token = await context.getToken();
if (!token) {
return false;
}
};
export function checkAttributesScope<T extends Record<string, any>>(data: T, attributes: Array<keyof T>) {
const attrs = attributes.filter(
attr => !data.hasOwnProperty(attr)
) as string[];
if (attrs.length > 0) {
throw new OakInputIllegalException(attrs, '多余的属性');
const { playerId } = token!;
const count = await context.rowStore.count('userRole', {
filter: {
userId: playerId!,
roleId: ROOT_ROLE_ID,
},
}, context);
if (count === 0) {
// 只有root允许扮演其他用户身份
return false;
}
return true;
}

View File

@ -77,7 +77,7 @@
"node_modules",
"**/*.spec.ts",
"test",
"scripts"/* ,
"wechatMp" */
"scripts",
"wechatMp"
]
}

View File

@ -1,78 +0,0 @@
"use strict";
Component({
properties: {
// default, primary, ghost, info, success, warning, error
type: {
type: String,
value: '',
},
inline: {
type: Boolean,
value: false
},
// default, large, small
size: {
type: String,
value: '',
},
// circle, square
shape: {
type: String,
value: 'square'
},
disabled: {
type: Boolean,
value: false,
},
loading: {
type: Boolean,
value: false,
},
long: {
type: Boolean,
value: false
},
openType: String,
appParameter: String,
hoverStopPropagation: Boolean,
hoverStartTime: {
type: Number,
value: 20
},
hoverStayTime: {
type: Number,
value: 70
},
lang: {
type: String,
value: 'en'
},
sessionFrom: {
type: String,
value: ''
},
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: Boolean
},
methods: {
handleTap() {
if (this.data.disabled)
return false;
this.triggerEvent('click');
},
bindgetuserinfo({ detail = {} } = {}) {
this.triggerEvent('getuserinfo', detail);
},
bindcontact({ detail = {} } = {}) {
this.triggerEvent('contact', detail);
},
bindgetphonenumber({ detail = {} } = {}) {
this.triggerEvent('getphonenumber', detail);
},
binderror({ detail = {} } = {}) {
this.triggerEvent('error', detail);
}
}
});

View File

@ -1,20 +0,0 @@
"use strict";
Component({
properties: {
name: String,
color: {
type: String,
value: '#3963bc'
},
size: {
type: String,
value: '44'
},
},
ready: function () {
if (!this.properties.name) {
console.error('请传入Icon组件的name属性');
}
},
methods: {}
});

View File

@ -1,56 +0,0 @@
"use strict";
Component({
behaviors: ['wx://form-field'],
properties: {
title: {
type: String
},
// text || textarea || password || number
type: {
type: String,
value: 'text'
},
disabled: {
type: Boolean,
value: false
},
placeholder: {
type: String,
value: ''
},
focus: {
type: Boolean,
value: false
},
mode: {
type: String,
value: 'normal'
},
right: {
type: Boolean,
value: false
},
error: {
type: Boolean,
value: false
},
maxlength: {
type: Number,
value: 140,
}
},
methods: {
handleInputChange(event) {
const { detail } = event;
const { value } = detail;
this.setData({ value });
this.triggerEvent('change', event.detail);
},
handleInputFocus(event) {
this.triggerEvent('focus', event.detail);
},
handleInputBlur(event) {
this.triggerEvent('blur', event.detail);
}
}
});

View File

@ -1,8 +0,0 @@
"use strict";
// index.ts
OakComponent({
entity: 'area',
formData: async ([area]) => ({
name: area.name,
}),
}, {});

View File

@ -1,43 +0,0 @@
"use strict";
// index.ts
OakPage({
path: 'address:list',
entity: 'address',
projection: {
id: 1,
name: 1,
phone: 1,
detail: 1,
area: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
},
},
},
},
isList: true,
formData: async (addresses) => ({
addresses: addresses.map((address) => ({
name: address?.name,
phone: address?.phone,
districtName: address?.area?.name,
areaText: address?.area && `${address?.area?.parent?.parent?.name}${address?.area?.parent?.name}${address?.area?.name}`,
detail: address?.detail,
})),
}),
}, {
methods: {
goNewAddress() {
this.data.a;
this.navigateTo({
url: '../upsert/index',
});
}
}
});

View File

@ -1,55 +0,0 @@
"use strict";
OakPage({
path: 'address:upsert',
entity: 'address',
projection: {
id: 1,
name: 1,
phone: 1,
detail: 1,
area: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
},
},
},
},
isList: false,
formData: async ([address]) => ({
name: address?.name,
phone: address?.phone,
// areaName: `${address?.area?.parent.parent.name}${address?.area?.parent.name}${address?.area?.name}`,
// provinceName: address?.area?.parent.parent.name,
districtName: address?.area?.name,
area: address?.area,
areaText: address?.area && `${address?.area?.parent?.parent?.name}${address?.area?.parent?.name}${address?.area?.name}`,
detail: address?.detail,
}),
}, {
methods: {
setValue(input) {
const { target, detail } = input;
const { dataset: { attr } } = target;
const { value } = detail;
this.setUpdateData(attr, value);
},
callAreaPicker() {
this.callPicker('area', {
depth: 3,
});
},
async confirm() {
await this.execute(this.data.oakId ? 'update' : 'create', () => {
if (this.data.oakFrom === 'address:list') {
wx.navigateBack();
}
});
}
}
});

View File

@ -1,6 +0,0 @@
"use strict";
Page({
handleClick() {
console.log('btn');
}
});

View File

@ -1,15 +0,0 @@
"use strict";
Page({
data: {
value1: '',
value2: '',
value3: '',
value4: '输入框已禁用',
value5: '',
value6: '',
value7: ''
},
changeValue(e) {
console.log(e);
}
});

View File

@ -1,7 +0,0 @@
"use strict";
Page({
navigateToCpnPage(e) {
const pagename = e.currentTarget.dataset.value;
wx.navigateTo({ url: `../g-${pagename}/index` });
}
});

View File

@ -1 +0,0 @@
export {};

View File

@ -1,32 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
OakPage({
path: 'mobile:me',
entity: 'mobile',
isList: true,
projection: {
id: 1,
mobile: 1,
userId: 1,
},
formData: async (mobiles) => ({
mobiles,
}),
}, {
methods: {
async onRefreshMobile(e) {
this.setData({
refreshing: true,
});
try {
console.log(e.detail.code);
}
catch (err) {
console.error(err);
}
this.setData({
refreshing: false,
});
}
}
});

View File

@ -1,40 +0,0 @@
"use strict";
OakPage({
path: 'area:picker',
entity: 'area',
projection: {
id: 1,
name: 1,
depth: 1,
level: 1,
},
filters: [
{
parent: {
level: 'country',
},
}
],
isList: true,
formData: async (arealist) => ({
arealist,
}),
}, {
properties: {
depth: Number,
},
methods: {
onItemClicked(options) {
const item = (this.data.arealist).find((ele) => ele.id === options.currentTarget.dataset.id);
const { depth, id } = item;
if (depth !== this.data.depth) {
this.setFilters([{
parentId: id,
}]);
}
else {
this.setForeignKey(id);
}
}
}
});

View File

@ -1 +0,0 @@
export {};

View File

@ -1,37 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
OakPage({
path: 'token:login',
entity: 'token',
projection: {
id: 1,
wechatUser: {
id: 1,
},
userId: 1,
playerId: 1,
},
isList: true,
formData: async (tokenList, features) => {
const tokenValue = await features.token.getToken();
if (tokenValue) {
return {
loggedIn: true,
};
}
return {
loggedIn: false,
};
},
}, {
methods: {
async onLoginClicked(options) {
const { code } = await wx.login();
const env = await wx.getSystemInfo();
await this.features.token.loginWechatMp('token:login');
},
onReturnClicked() {
wx.navigateBack();
}
}
});

View File

@ -1 +0,0 @@
export {};

View File

@ -1,117 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../../../../src/constants");
const extraFile_1 = require("../../../../src/utils/extraFile");
OakPage({
path: 'token:me',
entity: 'token',
isList: true,
projection: {
id: 1,
userId: 1,
playerId: 1,
user: {
id: 1,
nickname: 1,
name: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
},
filter: {
tag1: 'avatar',
},
indexFrom: 0,
count: 1,
},
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
},
},
},
player: {
id: 1,
userRole$user: {
$entity: 'userRole',
data: {
id: 1,
userId: 1,
roleId: 1,
}
},
}
},
formData: async ([token]) => {
const user = token?.user;
const player = token?.player;
const avatarFile = user && user.extraFile$entity && user.extraFile$entity[0];
const avatar = avatarFile && (0, extraFile_1.composeFileUrl)(avatarFile);
const nickname = user && user.nickname;
const mobileData = user && user.mobile$user && user.mobile$user[0];
const { mobile } = mobileData || {};
const mobileCount = user?.mobile$user?.length || 0;
const isLoggedIn = !!token;
const isPlayingAnother = token && token.userId !== token.playerId;
const isRoot = player?.userRole$user && player.userRole$user[0].roleId === constants_1.ROOT_ROLE_ID;
return {
avatar,
nickname,
mobile,
mobileCount,
isLoggedIn,
isPlayingAnother,
isRoot,
};
},
}, {
methods: {
async onRefresh() {
this.setData({
refreshing: true,
});
try {
await this.features.token.syncUserInfoWechatMp('token:me');
}
catch (err) {
console.error(err);
}
this.setData({
refreshing: false,
});
},
async doLogin() {
this.setData({
refreshing: true,
});
try {
await this.features.token.loginWechatMp('token:me');
}
catch (err) {
console.error(err);
}
this.setData({
refreshing: false,
});
},
goMyMobile() {
this.navigateTo({
url: '../../mobile/me/index',
});
},
goUserManage() {
this.navigateTo({
url: '../../user/manage/index',
});
}
}
});

View File

@ -1 +0,0 @@
export {};

View File

@ -1,57 +0,0 @@
"use strict";
// index.ts
Object.defineProperty(exports, "__esModule", { value: true });
const extraFile_1 = require("../../../../../src/utils/extraFile");
OakPage({
path: 'user:manage:detail',
entity: 'user',
projection: {
id: 1,
nickname: 1,
name: 1,
userState: 1,
idState: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
},
filter: {
tag1: 'avatar',
},
indexFrom: 0,
count: 1,
},
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
},
},
},
isList: false,
formData: async ([user]) => {
const { id, nickname, idState, userState, name, mobile$user, extraFile$entity } = user;
const mobile = mobile$user && mobile$user[0]?.mobile;
const avatar = extraFile$entity && extraFile$entity[0] && (0, extraFile_1.composeFileUrl)(extraFile$entity[0]);
return {
id,
nickname,
name,
mobile,
avatar,
userState,
idState,
};
},
actions: ['accept', 'activate', 'disable', 'enable', 'remove', 'update', 'verify'],
}, {
methods: {}
});

View File

@ -51,7 +51,7 @@ OakPage({
idState,
};
},
actions: ['accept', 'activate', 'disable', 'enable', 'remove', 'update', 'verify'],
actions: ['accept', 'activate', 'disable', 'enable', 'remove', 'update', 'verify', 'play'],
}, {
data: {
actionDescriptions: {
@ -96,11 +96,17 @@ OakPage({
name: 'how_to_reg',
},
label: '验证',
},
play: {
icon: {
name: 'play_circle',
},
label: '切换',
}
}
},
methods: {
onActionClick({ detail }: WechatMiniprogram.CustomEvent) {
async onActionClick({ detail }: WechatMiniprogram.CustomEvent) {
const { action } = detail;
switch (action) {
case 'update': {
@ -108,12 +114,26 @@ OakPage({
url: '../upsert/index',
oakId: this.data.oakId,
});
return;
}
case 'enable':
case 'disable':
case 'accept':
case 'verify':
case 'activate':
case 'play': {
await this.execute(action);
break;
}
default: {
console.error(`尚未实现的action: ${action}`)
}
}
if (action === 'play') {
wx.navigateBack({
delta: 2,
});
}
}
}
});

View File

@ -1 +0,0 @@
export {};

View File

@ -1,72 +0,0 @@
"use strict";
// index.ts
Object.defineProperty(exports, "__esModule", { value: true });
const extraFile_1 = require("../../../../src/utils/extraFile");
OakPage({
path: 'user:manage',
entity: 'user',
projection: {
id: 1,
nickname: 1,
name: 1,
userState: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
},
filter: {
tag1: 'avatar',
},
indexFrom: 0,
count: 1,
},
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
},
},
},
isList: true,
formData: async (users) => {
const userData = users.map((user) => {
const { id, nickname, userState, name, mobile$user, extraFile$entity } = user;
const mobile = mobile$user && mobile$user[0]?.mobile;
const avatar = extraFile$entity && extraFile$entity[0] && (0, extraFile_1.composeFileUrl)(extraFile$entity[0]);
return {
id,
nickname,
name,
mobile,
avatar,
userState,
};
});
return {
userData,
};
},
}, {
methods: {
goUserManageDetail(options) {
const { id } = options.currentTarget.dataset;
this.navigateTo({
url: 'detail/index',
oakId: id,
});
},
goNewUser() {
this.navigateTo({
url: 'upsert/index',
});
},
}
});

View File

@ -1 +0,0 @@
export {};

View File

@ -1,101 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const GenderOptions = [
{
value: 'male', label: '男',
},
{
value: 'female', label: '女',
}
];
const IDCardTypeOptions = [
{
value: 'ID-Card', label: '身份证',
},
{
value: 'passport', label: '护照',
},
{
value: 'Mainland-passport', label: '港澳通行证',
}
];
OakPage({
path: 'user:manage:upsert',
entity: 'user',
projection: {
id: 1,
name: 1,
nickname: 1,
birth: 1,
gender: 1,
avatar: 1,
idCardType: 1,
idNumber: 1,
},
isList: false,
formData: async ([user]) => {
const { birth, gender, idCardType } = user || {};
const birthText = birth && (new Date(birth)).toLocaleDateString();
const GenderDict = {
male: '男',
female: '女',
};
const genderText = gender && GenderDict[gender];
const genderIndex = gender && GenderOptions.find(ele => ele.value === gender);
const IdCardTypeDict = {
'ID-Card': '身份证',
'passport': '护照',
'Mainland-passport': '港澳通行证',
};
const idCardTypeText = idCardType && IdCardTypeDict[idCardType];
const idCardTypeIndex = idCardType && IDCardTypeOptions.find(ele => ele.value === gender);
const now = new Date();
return (0, lodash_1.assign)({}, user, {
birthText,
genderText,
idCardTypeText,
oldestBirthday: `${now.getFullYear() - 120}-01-01`,
today: `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`,
genderIndex,
idCardTypeIndex,
});
},
}, {
data: {
GenderOptions,
IDCardTypeOptions,
},
methods: {
setValue(input) {
const { target, detail } = input;
const { dataset: { attr } } = target;
const { value } = detail;
this.setUpdateData(attr, value);
},
onBirthChange(e) {
const { value } = e.detail;
const birth = new Date(value);
birth.setHours(0);
birth.setMinutes(0);
birth.setSeconds(0);
birth.setMilliseconds(0);
this.setUpdateData('birth', birth);
},
onGenderChange(e) {
const { value } = e.detail;
this.setUpdateData('gender', GenderOptions[value].value);
},
onIdCardTypeChange(e) {
const { value } = e.detail;
this.setUpdateData('idCardType', IDCardTypeOptions[value].value);
},
async confirm() {
await this.execute(this.data.oakId ? 'update' : 'create', () => {
if (this.data.oakFrom === 'user:manage:list') {
wx.navigateBack();
}
});
}
}
});