Merge branch 'release'
This commit is contained in:
commit
3d539b93db
|
|
@ -1123,7 +1123,8 @@ function constructFilter(statements, entity) {
|
||||||
case 'Int':
|
case 'Int':
|
||||||
case 'Uint':
|
case 'Uint':
|
||||||
case 'Float':
|
case 'Float':
|
||||||
case 'Double': {
|
case 'Double':
|
||||||
|
case 'Price': {
|
||||||
type2 = factory.createTypeReferenceNode(factory.createIdentifier('Q_NumberValue'));
|
type2 = factory.createTypeReferenceNode(factory.createIdentifier('Q_NumberValue'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1276,7 +1277,8 @@ function constructProjection(statements, entity) {
|
||||||
case 'File':
|
case 'File':
|
||||||
case 'SingleGeo':
|
case 'SingleGeo':
|
||||||
case 'Geo':
|
case 'Geo':
|
||||||
case 'Object': {
|
case 'Object':
|
||||||
|
case 'Price': {
|
||||||
properties.push([name_4, false]);
|
properties.push([name_4, false]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1639,7 +1641,8 @@ function constructSorter(statements, entity) {
|
||||||
case 'Boolean':
|
case 'Boolean':
|
||||||
case 'Datetime':
|
case 'Datetime':
|
||||||
case 'Image':
|
case 'Image':
|
||||||
case 'File': {
|
case 'File':
|
||||||
|
case 'Price': {
|
||||||
type2 = factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
|
type2 = factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2658,6 +2661,7 @@ var initialStatements = function () { return [
|
||||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Text')),
|
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Text')),
|
||||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Datetime')),
|
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Datetime')),
|
||||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('File')),
|
factory.createImportSpecifier(false, undefined, factory.createIdentifier('File')),
|
||||||
|
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Price')),
|
||||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Image')),
|
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Image')),
|
||||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('PrimaryKey')),
|
factory.createImportSpecifier(false, undefined, factory.createIdentifier('PrimaryKey')),
|
||||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('ForeignKey')),
|
factory.createImportSpecifier(false, undefined, factory.createIdentifier('ForeignKey')),
|
||||||
|
|
@ -2934,15 +2938,13 @@ function constructAttributes(entity) {
|
||||||
], true)));
|
], true)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'Float': {
|
case 'Double':
|
||||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("float")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
case 'Float':
|
||||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(typeArguments[0].literal.text)),
|
case 'Decimal': {
|
||||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(typeArguments[1].literal.text))
|
if (['Double', 'Float'].includes(text)) {
|
||||||
], true)));
|
console.warn("".concat(entity, "\u5BF9\u8C61\u4E2D\u8FD8\u6709").concat(text, "\u7C7B\u578B\u5B9A\u4E49\uFF0C\u73B0\u5728\u7EDF\u4E00\u7528Decimal\u8FDB\u884C\u5B58\u50A8"));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 'Double': {
|
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("decimal")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("double")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
|
||||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(typeArguments[0].literal.text)),
|
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(typeArguments[0].literal.text)),
|
||||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(typeArguments[1].literal.text))
|
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(typeArguments[1].literal.text))
|
||||||
], true)));
|
], true)));
|
||||||
|
|
@ -2952,6 +2954,10 @@ function constructAttributes(entity) {
|
||||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("boolean")));
|
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("boolean")));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'Price': {
|
||||||
|
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("money")));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'Datetime': {
|
case 'Datetime': {
|
||||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("datetime")));
|
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("datetime")));
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ var indexes = [
|
||||||
];
|
];
|
||||||
var locale = {
|
var locale = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '更新',
|
||||||
attr: {
|
attr: {
|
||||||
targetEntity: '目标对象',
|
targetEntity: '目标对象',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ var config = {
|
||||||
};
|
};
|
||||||
var locale = {
|
var locale = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '更新对象连接',
|
||||||
attr: {
|
attr: {
|
||||||
modi: '更新',
|
modi: '更新',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ var configuration = {
|
||||||
};
|
};
|
||||||
var locale = {
|
var locale = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '操作',
|
||||||
attr: {
|
attr: {
|
||||||
action: '动作',
|
action: '动作',
|
||||||
data: '数据',
|
data: '数据',
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ var config = {
|
||||||
};
|
};
|
||||||
var locale = {
|
var locale = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '操作对象连接',
|
||||||
attr: {
|
attr: {
|
||||||
oper: '操作',
|
oper: '操作',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ var UserActionDef = {
|
||||||
};
|
};
|
||||||
var locale = {
|
var locale = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '用户',
|
||||||
attr: {
|
attr: {
|
||||||
name: '姓名',
|
name: '姓名',
|
||||||
nickname: '昵称',
|
nickname: '昵称',
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
;
|
;
|
||||||
var locale = {
|
var locale = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '用户授权',
|
||||||
attr: {
|
attr: {
|
||||||
relation: '关系',
|
relation: '关系',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -64,93 +64,91 @@ var AsyncContext = /** @class */ (function () {
|
||||||
};
|
};
|
||||||
AsyncContext.prototype.commit = function () {
|
AsyncContext.prototype.commit = function () {
|
||||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
var _a, _b, e, e_1_1;
|
var commitEvents, commitEvents_1, commitEvents_1_1, e, e_1_1;
|
||||||
var e_1, _c;
|
var e_1, _a;
|
||||||
return tslib_1.__generator(this, function (_d) {
|
return tslib_1.__generator(this, function (_b) {
|
||||||
switch (_d.label) {
|
switch (_b.label) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!this.uuid) return [3 /*break*/, 10];
|
if (!this.uuid) return [3 /*break*/, 9];
|
||||||
return [4 /*yield*/, this.rowStore.commit(this.uuid)];
|
return [4 /*yield*/, this.rowStore.commit(this.uuid)];
|
||||||
case 1:
|
case 1:
|
||||||
_d.sent();
|
_b.sent();
|
||||||
this.uuid = undefined;
|
this.uuid = undefined;
|
||||||
_d.label = 2;
|
commitEvents = this.events.commit;
|
||||||
|
this.resetEvents();
|
||||||
|
_b.label = 2;
|
||||||
case 2:
|
case 2:
|
||||||
_d.trys.push([2, 7, 8, 9]);
|
_b.trys.push([2, 7, 8, 9]);
|
||||||
_a = tslib_1.__values(this.events.commit), _b = _a.next();
|
commitEvents_1 = tslib_1.__values(commitEvents), commitEvents_1_1 = commitEvents_1.next();
|
||||||
_d.label = 3;
|
_b.label = 3;
|
||||||
case 3:
|
case 3:
|
||||||
if (!!_b.done) return [3 /*break*/, 6];
|
if (!!commitEvents_1_1.done) return [3 /*break*/, 6];
|
||||||
e = _b.value;
|
e = commitEvents_1_1.value;
|
||||||
return [4 /*yield*/, e()];
|
return [4 /*yield*/, e()];
|
||||||
case 4:
|
case 4:
|
||||||
_d.sent();
|
_b.sent();
|
||||||
_d.label = 5;
|
_b.label = 5;
|
||||||
case 5:
|
case 5:
|
||||||
_b = _a.next();
|
commitEvents_1_1 = commitEvents_1.next();
|
||||||
return [3 /*break*/, 3];
|
return [3 /*break*/, 3];
|
||||||
case 6: return [3 /*break*/, 9];
|
case 6: return [3 /*break*/, 9];
|
||||||
case 7:
|
case 7:
|
||||||
e_1_1 = _d.sent();
|
e_1_1 = _b.sent();
|
||||||
e_1 = { error: e_1_1 };
|
e_1 = { error: e_1_1 };
|
||||||
return [3 /*break*/, 9];
|
return [3 /*break*/, 9];
|
||||||
case 8:
|
case 8:
|
||||||
try {
|
try {
|
||||||
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
if (commitEvents_1_1 && !commitEvents_1_1.done && (_a = commitEvents_1.return)) _a.call(commitEvents_1);
|
||||||
}
|
}
|
||||||
finally { if (e_1) throw e_1.error; }
|
finally { if (e_1) throw e_1.error; }
|
||||||
return [7 /*endfinally*/];
|
return [7 /*endfinally*/];
|
||||||
case 9:
|
case 9: return [2 /*return*/];
|
||||||
this.resetEvents();
|
|
||||||
_d.label = 10;
|
|
||||||
case 10: return [2 /*return*/];
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
AsyncContext.prototype.rollback = function () {
|
AsyncContext.prototype.rollback = function () {
|
||||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
var _a, _b, e, e_2_1;
|
var rollbackEvents, rollbackEvents_1, rollbackEvents_1_1, e, e_2_1;
|
||||||
var e_2, _c;
|
var e_2, _a;
|
||||||
return tslib_1.__generator(this, function (_d) {
|
return tslib_1.__generator(this, function (_b) {
|
||||||
switch (_d.label) {
|
switch (_b.label) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!this.uuid) return [3 /*break*/, 10];
|
if (!this.uuid) return [3 /*break*/, 9];
|
||||||
return [4 /*yield*/, this.rowStore.rollback(this.uuid)];
|
return [4 /*yield*/, this.rowStore.rollback(this.uuid)];
|
||||||
case 1:
|
case 1:
|
||||||
_d.sent();
|
_b.sent();
|
||||||
// console.log('rollback', this.uuid);
|
// console.log('rollback', this.uuid);
|
||||||
this.uuid = undefined;
|
this.uuid = undefined;
|
||||||
_d.label = 2;
|
rollbackEvents = this.events.rollback;
|
||||||
|
this.resetEvents();
|
||||||
|
_b.label = 2;
|
||||||
case 2:
|
case 2:
|
||||||
_d.trys.push([2, 7, 8, 9]);
|
_b.trys.push([2, 7, 8, 9]);
|
||||||
_a = tslib_1.__values(this.events.rollback), _b = _a.next();
|
rollbackEvents_1 = tslib_1.__values(rollbackEvents), rollbackEvents_1_1 = rollbackEvents_1.next();
|
||||||
_d.label = 3;
|
_b.label = 3;
|
||||||
case 3:
|
case 3:
|
||||||
if (!!_b.done) return [3 /*break*/, 6];
|
if (!!rollbackEvents_1_1.done) return [3 /*break*/, 6];
|
||||||
e = _b.value;
|
e = rollbackEvents_1_1.value;
|
||||||
return [4 /*yield*/, e()];
|
return [4 /*yield*/, e()];
|
||||||
case 4:
|
case 4:
|
||||||
_d.sent();
|
_b.sent();
|
||||||
_d.label = 5;
|
_b.label = 5;
|
||||||
case 5:
|
case 5:
|
||||||
_b = _a.next();
|
rollbackEvents_1_1 = rollbackEvents_1.next();
|
||||||
return [3 /*break*/, 3];
|
return [3 /*break*/, 3];
|
||||||
case 6: return [3 /*break*/, 9];
|
case 6: return [3 /*break*/, 9];
|
||||||
case 7:
|
case 7:
|
||||||
e_2_1 = _d.sent();
|
e_2_1 = _b.sent();
|
||||||
e_2 = { error: e_2_1 };
|
e_2 = { error: e_2_1 };
|
||||||
return [3 /*break*/, 9];
|
return [3 /*break*/, 9];
|
||||||
case 8:
|
case 8:
|
||||||
try {
|
try {
|
||||||
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
if (rollbackEvents_1_1 && !rollbackEvents_1_1.done && (_a = rollbackEvents_1.return)) _a.call(rollbackEvents_1);
|
||||||
}
|
}
|
||||||
finally { if (e_2) throw e_2.error; }
|
finally { if (e_2) throw e_2.error; }
|
||||||
return [7 /*endfinally*/];
|
return [7 /*endfinally*/];
|
||||||
case 9:
|
case 9: return [2 /*return*/];
|
||||||
this.resetEvents();
|
|
||||||
_d.label = 10;
|
|
||||||
case 10: return [2 /*return*/];
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -339,12 +339,18 @@ function translateCascadeRelationFilterMaker(schema, lch, entity2, pathPrefix) {
|
||||||
};
|
};
|
||||||
var filterMaker = paths.length ? translateFilterMakerIter(entity2, 0) : translateRelationFilter(entity2);
|
var filterMaker = paths.length ? translateFilterMakerIter(entity2, 0) : translateRelationFilter(entity2);
|
||||||
if (!paths.length) {
|
if (!paths.length) {
|
||||||
|
// 不可能是create
|
||||||
return function (oper, userId) { return filterMaker(userId); };
|
return function (oper, userId) { return filterMaker(userId); };
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 针对第一层做一下特别优化,比如对象A指向对象B(多对一),如果A的cascadePath是 'B',
|
* 针对第一层做一下特别优化,比如对象A指向对象B(多对一),如果A的cascadePath是 'B',
|
||||||
* 当create A时,会带有Bid。此时生成该B对象上的相关表达式查询返回,可以避免必须将此判定在对象创建之后再做
|
* 当create A时,会带有Bid。此时生成该B对象上的相关表达式查询返回,可以避免必须将此判定在对象创建之后再做
|
||||||
* 另一使用场景是,在查询A时,如果带有Bid(在对象跳一对多子对象场景下很常见),可以提前判定这个查询对某些用户一定返回空集
|
* 另一使用场景是,在查询A时,如果带有Bid(在对象跳一对多子对象场景下很常见),可以提前判定这个查询对某些用户一定返回空集
|
||||||
|
*
|
||||||
|
* 20230306:
|
||||||
|
* 在前台的权限判断中,会将list上的filter当成内在的限制对create动作进行判断,此时有一种可能是,filter并不能直接判断出外键,但会限制外键的查询范围。
|
||||||
|
* 例如,在jichuang项目中,就存在park/list上,平台的用户去访问时,其查询条件是{ system: { platformId: 1 }};而用户的关系落在system.platform.platformProvider上,
|
||||||
|
* 此时如直接通过data上的外键判断就会失败,需要通过对filter上相应的语义解构,进行进一步的判断
|
||||||
*/
|
*/
|
||||||
var _a = tslib_1.__read(paths, 1), attr = _a[0];
|
var _a = tslib_1.__read(paths, 1), attr = _a[0];
|
||||||
var relation = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
var relation = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
||||||
|
|
@ -352,14 +358,76 @@ function translateCascadeRelationFilterMaker(schema, lch, entity2, pathPrefix) {
|
||||||
var filterMaker2 = paths.length > 1
|
var filterMaker2 = paths.length > 1
|
||||||
? (relation === 2 ? translateFilterMakerIter(attr, 1) : translateFilterMakerIter(relation, 1))
|
? (relation === 2 ? translateFilterMakerIter(attr, 1) : translateFilterMakerIter(relation, 1))
|
||||||
: (relation === 2 ? translateRelationFilter(attr) : translateRelationFilter(relation));
|
: (relation === 2 ? translateRelationFilter(attr) : translateRelationFilter(relation));
|
||||||
|
var translateCreateFilterMaker = function (entity, filter, userId) {
|
||||||
|
var counters = [];
|
||||||
|
if (filter) {
|
||||||
|
if (relation === 2) {
|
||||||
|
if (filter.entity === entity && filter.entityId) {
|
||||||
|
// 这里对entityId的限定的数据只要和userId有一条relation,就不能否定可能会有创建动作(外键在最终create时,data上一定会有判定)
|
||||||
|
counters.push({
|
||||||
|
$entity: attr,
|
||||||
|
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: filter.entityId }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (filter[attr]) {
|
||||||
|
counters.push({
|
||||||
|
$entity: attr,
|
||||||
|
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), filter[attr]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(0, assert_1.default)(typeof relation === 'string');
|
||||||
|
if (filter["".concat(attr, "Id")]) {
|
||||||
|
var filterMaker3 = paths.length > 1 ? translateFilterMakerIter(relation, 1) : translateRelationFilter(relation);
|
||||||
|
// 这里对attrId的限定的数据只要和userId有一条relation,就不能否定可能会有创建动作(外键在最终create时,data上一定会有判定)
|
||||||
|
counters.push({
|
||||||
|
$entity: relation,
|
||||||
|
$filter: (0, filter_1.addFilterSegment)(filterMaker3(userId), { id: filter["".concat(attr, "Id")] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (filter[attr]) {
|
||||||
|
counters.push({
|
||||||
|
$entity: relation,
|
||||||
|
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), filter[attr]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filter.$and) {
|
||||||
|
var countersAnd = filter.$and.map(function (ele) { return translateCreateFilterMaker(entity, ele, userId); });
|
||||||
|
// and 只要有一个满足就行
|
||||||
|
var ca2 = countersAnd.filter(function (ele) { return !(ele instanceof Exception_1.OakUserUnpermittedException); });
|
||||||
|
counters.push.apply(counters, tslib_1.__spreadArray([], tslib_1.__read(ca2), false));
|
||||||
|
}
|
||||||
|
if (filter.$or) {
|
||||||
|
var countersOr = filter.$and.map(function (ele) { return translateCreateFilterMaker(entity, ele, userId); });
|
||||||
|
// or也只要有一个满足就行(不能否定)
|
||||||
|
var co2 = countersOr.filter(function (ele) { return !(ele instanceof Exception_1.OakUserUnpermittedException); });
|
||||||
|
counters.push.apply(counters, tslib_1.__spreadArray([], tslib_1.__read(co2), false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (counters.length === 0) {
|
||||||
|
// 一个counter都找不出来,说明当前路径上不满足
|
||||||
|
return new Exception_1.OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
else if (counters.length === 1) {
|
||||||
|
return counters[0];
|
||||||
|
}
|
||||||
|
// 是or关系,只要其中有一个满足就可以通过
|
||||||
|
return {
|
||||||
|
$$or: counters,
|
||||||
|
};
|
||||||
|
};
|
||||||
return function (operation, userId) {
|
return function (operation, userId) {
|
||||||
var action = operation.action;
|
var action = operation.action;
|
||||||
if (action === 'create') {
|
if (action === 'create') {
|
||||||
var data = operation.data;
|
var data = operation.data;
|
||||||
|
if (data) {
|
||||||
|
// 有data的情形根据data判定
|
||||||
var getForeignKeyId_1 = function (d) {
|
var getForeignKeyId_1 = function (d) {
|
||||||
if (relation === 2) {
|
if (relation === 2) {
|
||||||
if (d.entity === attr && typeof d.entityId === 'string') {
|
if (d.entity === attr && typeof d.entityId === 'string') {
|
||||||
return d.entitId;
|
return d.entityId;
|
||||||
}
|
}
|
||||||
throw new Exception_1.OakUserUnpermittedException();
|
throw new Exception_1.OakUserUnpermittedException();
|
||||||
}
|
}
|
||||||
|
|
@ -401,6 +469,19 @@ function translateCascadeRelationFilterMaker(schema, lch, entity2, pathPrefix) {
|
||||||
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: fkId }),
|
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: fkId }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// todo
|
||||||
|
var filter_4 = operation.filter;
|
||||||
|
if (filter_4) {
|
||||||
|
var counter = translateCreateFilterMaker(entity2, filter_4, userId);
|
||||||
|
if (counter instanceof Exception_1.OakUserUnpermittedException) {
|
||||||
|
throw counter;
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
throw new Exception_1.OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
var filter = operation.filter;
|
var filter = operation.filter;
|
||||||
if (relation === 2 && (filter === null || filter === void 0 ? void 0 : filter.entity) === attr && (filter === null || filter === void 0 ? void 0 : filter.entityId)) {
|
if (relation === 2 && (filter === null || filter === void 0 ? void 0 : filter.entity) === attr && (filter === null || filter === void 0 ? void 0 : filter.entityId)) {
|
||||||
if (typeof filter.entityId === 'string') {
|
if (typeof filter.entityId === 'string') {
|
||||||
|
|
@ -450,8 +531,77 @@ function translateActionAuthFilterMaker(schema, relationItem, entity, pathPrefix
|
||||||
var filterMaker = translateCascadeRelationFilterMaker(schema, relationItem, entity, pathPrefix);
|
var filterMaker = translateCascadeRelationFilterMaker(schema, relationItem, entity, pathPrefix);
|
||||||
return filterMaker;
|
return filterMaker;
|
||||||
}
|
}
|
||||||
|
function execCreateCounter(context, counter) {
|
||||||
|
if (counter === null || counter === void 0 ? void 0 : counter.$$and) {
|
||||||
|
// 每个counter都要满足才能过
|
||||||
|
var counters = counter === null || counter === void 0 ? void 0 : counter.$$and;
|
||||||
|
(0, assert_1.default)(counters.length > 0);
|
||||||
|
var counterResults = counters.map(function (ele) { return execCreateCounter(context, ele); });
|
||||||
|
if (counterResults[0] instanceof Promise) {
|
||||||
|
return Promise.all(counterResults)
|
||||||
|
.then(function (cr2) {
|
||||||
|
var unpermitted = cr2.find(function (ele) { return ele instanceof Exception_1.OakUserUnpermittedException; });
|
||||||
|
if (unpermitted) {
|
||||||
|
return unpermitted;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var unpermitted = counterResults.find(function (ele) { return ele instanceof Exception_1.OakUserUnpermittedException; });
|
||||||
|
if (unpermitted) {
|
||||||
|
return unpermitted;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (counter === null || counter === void 0 ? void 0 : counter.$$or) {
|
||||||
|
// 只要有一个counter能过就算过
|
||||||
|
var counters = counter === null || counter === void 0 ? void 0 : counter.$$or;
|
||||||
|
(0, assert_1.default)(counters.length > 0);
|
||||||
|
var counterResults = counters.map(function (ele) { return execCreateCounter(context, ele); });
|
||||||
|
if (counterResults[0] instanceof Promise) {
|
||||||
|
return Promise.all(counterResults)
|
||||||
|
.then(function (cr2) {
|
||||||
|
var permittedIdx = cr2.indexOf(undefined);
|
||||||
|
if (permittedIdx !== -1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return new Exception_1.OakUserUnpermittedException();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var permittedIndex = counterResults.indexOf(undefined);
|
||||||
|
if (permittedIndex !== -1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Exception_1.OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (counter === null || counter === void 0 ? void 0 : counter.$entity) {
|
||||||
|
var _a = counter, $entity = _a.$entity, $filter = _a.$filter, _b = _a.$count, $count_1 = _b === void 0 ? 1 : _b;
|
||||||
|
var count = context.count($entity, {
|
||||||
|
filter: $filter,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
if (count instanceof Promise) {
|
||||||
|
return count.then(function (c2) {
|
||||||
|
if (c2 >= $count_1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return new Exception_1.OakUserUnpermittedException();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return count >= $count_1 ? undefined : new Exception_1.OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
function makePotentialFilter(operation, context, filterMaker) {
|
function makePotentialFilter(operation, context, filterMaker) {
|
||||||
var e_1, _a;
|
var e_1, _a, e_2, _b;
|
||||||
var userId = context.getCurrentUserId();
|
var userId = context.getCurrentUserId();
|
||||||
(0, assert_1.default)(userId);
|
(0, assert_1.default)(userId);
|
||||||
var filters = filterMaker instanceof Array ? filterMaker.map(function (ele) {
|
var filters = filterMaker instanceof Array ? filterMaker.map(function (ele) {
|
||||||
|
|
@ -470,38 +620,27 @@ function makePotentialFilter(operation, context, filterMaker) {
|
||||||
*/
|
*/
|
||||||
var filtersOr = [];
|
var filtersOr = [];
|
||||||
var isAsyncOr = false;
|
var isAsyncOr = false;
|
||||||
var _loop_1 = function (f) {
|
try {
|
||||||
var e_2, _b;
|
for (var filters_1 = tslib_1.__values(filters), filters_1_1 = filters_1.next(); !filters_1_1.done; filters_1_1 = filters_1.next()) {
|
||||||
|
var f = filters_1_1.value;
|
||||||
if (f instanceof Array) {
|
if (f instanceof Array) {
|
||||||
var isAsyncAnd = true;
|
var isAsyncAnd = false;
|
||||||
|
(0, assert_1.default)(f.length > 0);
|
||||||
var filtersAnd = [];
|
var filtersAnd = [];
|
||||||
var _loop_2 = function (ff) {
|
try {
|
||||||
if (ff === null || ff === void 0 ? void 0 : ff.$entity) {
|
for (var f_1 = (e_2 = void 0, tslib_1.__values(f)), f_1_1 = f_1.next(); !f_1_1.done; f_1_1 = f_1.next()) {
|
||||||
var _e = ff, $entity = _e.$entity, $filter = _e.$filter, _f = _e.$count, $count_1 = _f === void 0 ? 1 : _f;
|
var ff = f_1_1.value;
|
||||||
var count = context.count($entity, {
|
if ((ff === null || ff === void 0 ? void 0 : ff.$$and) || (ff === null || ff === void 0 ? void 0 : ff.$$or) || (ff === null || ff === void 0 ? void 0 : ff.$entity)) {
|
||||||
filter: $filter,
|
// 每个counter都要满足才能过
|
||||||
}, {});
|
var result = execCreateCounter(context, ff);
|
||||||
if (count instanceof Promise) {
|
if (result instanceof Promise) {
|
||||||
isAsyncAnd = true;
|
isAsyncAnd = true;
|
||||||
filtersAnd.push(count.then(function (c2) {
|
|
||||||
if (c2 >= $count_1) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return new Exception_1.OakUserUnpermittedException();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filtersAnd.push(count >= $count_1 ? undefined : new Exception_1.OakUserUnpermittedException());
|
|
||||||
}
|
}
|
||||||
|
filtersAnd.push(result);
|
||||||
}
|
}
|
||||||
else if (ff) {
|
else if (ff) {
|
||||||
filtersAnd.push(ff);
|
filtersAnd.push(ff);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
try {
|
|
||||||
for (var f_1 = (e_2 = void 0, tslib_1.__values(f)), f_1_1 = f_1.next(); !f_1_1.done; f_1_1 = f_1.next()) {
|
|
||||||
var ff = f_1_1.value;
|
|
||||||
_loop_2(ff);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
||||||
|
|
@ -545,28 +684,17 @@ function makePotentialFilter(operation, context, filterMaker) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (f === null || f === void 0 ? void 0 : f.$entity) {
|
if ((f === null || f === void 0 ? void 0 : f.$$and) || (f === null || f === void 0 ? void 0 : f.$$or) || (f === null || f === void 0 ? void 0 : f.$entity)) {
|
||||||
var _c = f, $entity = _c.$entity, $filter = _c.$filter, _d = _c.$count, $count_2 = _d === void 0 ? 1 : _d;
|
var counterResults = execCreateCounter(context, f);
|
||||||
var count = context.count($entity, {
|
if (counterResults instanceof Promise) {
|
||||||
filter: $filter,
|
|
||||||
}, {});
|
|
||||||
if (count instanceof Promise) {
|
|
||||||
isAsyncOr = true;
|
isAsyncOr = true;
|
||||||
filtersOr.push(count.then(function (c2) { return c2 >= $count_2 ? undefined : new Exception_1.OakUserUnpermittedException(); }));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filtersOr.push(count >= $count_2 ? undefined : new Exception_1.OakUserUnpermittedException());
|
|
||||||
}
|
}
|
||||||
|
filtersOr.push(counterResults);
|
||||||
}
|
}
|
||||||
else if (f) {
|
else if (f) {
|
||||||
filtersOr.push(f);
|
filtersOr.push(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
try {
|
|
||||||
for (var filters_1 = tslib_1.__values(filters), filters_1_1 = filters_1.next(); !filters_1_1.done; filters_1_1 = filters_1.next()) {
|
|
||||||
var f = filters_1_1.value;
|
|
||||||
_loop_1(f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||||
|
|
@ -603,18 +731,30 @@ function makePotentialFilter(operation, context, filterMaker) {
|
||||||
*/
|
*/
|
||||||
function createAuthCheckers(schema, authDict) {
|
function createAuthCheckers(schema, authDict) {
|
||||||
var checkers = [];
|
var checkers = [];
|
||||||
var _loop_3 = function (entity) {
|
var _loop_1 = function (entity) {
|
||||||
var _a;
|
var _a;
|
||||||
if (authDict[entity]) {
|
if (authDict[entity]) {
|
||||||
var _b = authDict[entity], relationAuth = _b.relationAuth, actionAuth = _b.actionAuth;
|
var _b = authDict[entity], relationAuth = _b.relationAuth, actionAuth = _b.actionAuth;
|
||||||
if (relationAuth) {
|
if (relationAuth) {
|
||||||
var raFilterMakerDict_1 = {};
|
var raFilterMakerDict_1 = {};
|
||||||
var userEntityName = "user".concat((0, string_1.firstLetterUpperCase)(entity));
|
var userEntityName = "user".concat((0, string_1.firstLetterUpperCase)(entity));
|
||||||
|
var allAuthItem = [];
|
||||||
for (var r in relationAuth) {
|
for (var r in relationAuth) {
|
||||||
|
var authItem = relationAuth[r];
|
||||||
Object.assign(raFilterMakerDict_1, (_a = {},
|
Object.assign(raFilterMakerDict_1, (_a = {},
|
||||||
_a[r] = translateActionAuthFilterMaker(schema, relationAuth[r], userEntityName, entity),
|
_a[r] = translateActionAuthFilterMaker(schema, authItem, userEntityName, entity),
|
||||||
_a));
|
_a));
|
||||||
|
if (authItem instanceof Array) {
|
||||||
|
allAuthItem.push.apply(allAuthItem, tslib_1.__spreadArray([], tslib_1.__read(authItem), false));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
allAuthItem.push(authItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果不指定relation,则使用所有的authItem的or组合
|
||||||
|
Object.assign(raFilterMakerDict_1, {
|
||||||
|
'@@all': translateActionAuthFilterMaker(schema, allAuthItem, userEntityName, entity),
|
||||||
|
});
|
||||||
var entityIdAttr_1 = "".concat(entity, "Id");
|
var entityIdAttr_1 = "".concat(entity, "Id");
|
||||||
checkers.push({
|
checkers.push({
|
||||||
entity: userEntityName,
|
entity: userEntityName,
|
||||||
|
|
@ -624,8 +764,12 @@ function createAuthCheckers(schema, authDict) {
|
||||||
var data = operation.data;
|
var data = operation.data;
|
||||||
(0, assert_1.default)(!(data instanceof Array));
|
(0, assert_1.default)(!(data instanceof Array));
|
||||||
var _a = data, relation = _a.relation, _b = entityIdAttr_1, entityId = _a[_b];
|
var _a = data, relation = _a.relation, _b = entityIdAttr_1, entityId = _a[_b];
|
||||||
|
if (!relation) {
|
||||||
|
// 不指定relation测试是否有创建权限
|
||||||
|
return makePotentialFilter(operation, context, raFilterMakerDict_1['@@all']);
|
||||||
|
}
|
||||||
if (!raFilterMakerDict_1[relation]) {
|
if (!raFilterMakerDict_1[relation]) {
|
||||||
return;
|
throw new Exception_1.OakUserUnpermittedException();
|
||||||
}
|
}
|
||||||
var filter = makePotentialFilter(operation, context, raFilterMakerDict_1[relation]);
|
var filter = makePotentialFilter(operation, context, raFilterMakerDict_1[relation]);
|
||||||
return filter;
|
return filter;
|
||||||
|
|
@ -694,7 +838,7 @@ function createAuthCheckers(schema, authDict) {
|
||||||
// todo 等实现的时候再写
|
// todo 等实现的时候再写
|
||||||
}
|
}
|
||||||
if (actionAuth) {
|
if (actionAuth) {
|
||||||
var _loop_4 = function (a) {
|
var _loop_2 = function (a) {
|
||||||
var filterMaker = translateActionAuthFilterMaker(schema, actionAuth[a], entity);
|
var filterMaker = translateActionAuthFilterMaker(schema, actionAuth[a], entity);
|
||||||
checkers.push({
|
checkers.push({
|
||||||
entity: entity,
|
entity: entity,
|
||||||
|
|
@ -709,13 +853,13 @@ function createAuthCheckers(schema, authDict) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
for (var a in actionAuth) {
|
for (var a in actionAuth) {
|
||||||
_loop_4(a);
|
_loop_2(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (var entity in schema) {
|
for (var entity in schema) {
|
||||||
_loop_3(entity);
|
_loop_1(entity);
|
||||||
}
|
}
|
||||||
return checkers;
|
return checkers;
|
||||||
}
|
}
|
||||||
|
|
@ -784,7 +928,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
}
|
}
|
||||||
// 当删除一时,要确认多上面没有指向一的数据
|
// 当删除一时,要确认多上面没有指向一的数据
|
||||||
var entities = (0, lodash_1.union)(Object.keys(OneToManyMatrix), Object.keys(OneToManyOnEntityMatrix));
|
var entities = (0, lodash_1.union)(Object.keys(OneToManyMatrix), Object.keys(OneToManyOnEntityMatrix));
|
||||||
var _loop_5 = function (entity) {
|
var _loop_3 = function (entity) {
|
||||||
checkers.push({
|
checkers.push({
|
||||||
entity: entity,
|
entity: entity,
|
||||||
action: 'remove',
|
action: 'remove',
|
||||||
|
|
@ -793,7 +937,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
var e_6, _a, e_7, _b;
|
var e_6, _a, e_7, _b;
|
||||||
var promises = [];
|
var promises = [];
|
||||||
if (OneToManyMatrix[entity]) {
|
if (OneToManyMatrix[entity]) {
|
||||||
var _loop_7 = function (otm) {
|
var _loop_5 = function (otm) {
|
||||||
var _g, _h;
|
var _g, _h;
|
||||||
var _j = tslib_1.__read(otm, 2), e = _j[0], attr = _j[1];
|
var _j = tslib_1.__read(otm, 2), e = _j[0], attr = _j[1];
|
||||||
var proj = (_g = {
|
var proj = (_g = {
|
||||||
|
|
@ -832,7 +976,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
try {
|
try {
|
||||||
for (var _c = (e_6 = void 0, tslib_1.__values(OneToManyMatrix[entity])), _d = _c.next(); !_d.done; _d = _c.next()) {
|
for (var _c = (e_6 = void 0, tslib_1.__values(OneToManyMatrix[entity])), _d = _c.next(); !_d.done; _d = _c.next()) {
|
||||||
var otm = _d.value;
|
var otm = _d.value;
|
||||||
_loop_7(otm);
|
_loop_5(otm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
||||||
|
|
@ -844,7 +988,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (OneToManyOnEntityMatrix[entity]) {
|
if (OneToManyOnEntityMatrix[entity]) {
|
||||||
var _loop_8 = function (otm) {
|
var _loop_6 = function (otm) {
|
||||||
var _l, _m, _o;
|
var _l, _m, _o;
|
||||||
var proj = {
|
var proj = {
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|
@ -890,7 +1034,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
try {
|
try {
|
||||||
for (var _e = (e_7 = void 0, tslib_1.__values(OneToManyOnEntityMatrix[entity])), _f = _e.next(); !_f.done; _f = _e.next()) {
|
for (var _e = (e_7 = void 0, tslib_1.__values(OneToManyOnEntityMatrix[entity])), _f = _e.next(); !_f.done; _f = _e.next()) {
|
||||||
var otm = _f.value;
|
var otm = _f.value;
|
||||||
_loop_8(otm);
|
_loop_6(otm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
||||||
|
|
@ -910,7 +1054,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
try {
|
try {
|
||||||
for (var entities_1 = tslib_1.__values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
|
for (var entities_1 = tslib_1.__values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
|
||||||
var entity = entities_1_1.value;
|
var entity = entities_1_1.value;
|
||||||
_loop_5(entity);
|
_loop_3(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
||||||
|
|
@ -920,13 +1064,13 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
}
|
}
|
||||||
finally { if (e_4) throw e_4.error; }
|
finally { if (e_4) throw e_4.error; }
|
||||||
}
|
}
|
||||||
var _loop_6 = function (entity) {
|
var _loop_4 = function (entity) {
|
||||||
var e_8, _b;
|
var e_8, _b;
|
||||||
var cascadeRemove = authDict[entity].cascadeRemove;
|
var cascadeRemove = authDict[entity].cascadeRemove;
|
||||||
if (cascadeRemove) {
|
if (cascadeRemove) {
|
||||||
var entitiesOnEntityAttr = [];
|
var entitiesOnEntityAttr = [];
|
||||||
var hasAllEntity = false;
|
var hasAllEntity = false;
|
||||||
var _loop_9 = function (attr) {
|
var _loop_7 = function (attr) {
|
||||||
if (attr === '@entity') {
|
if (attr === '@entity') {
|
||||||
hasAllEntity = true;
|
hasAllEntity = true;
|
||||||
return "continue";
|
return "continue";
|
||||||
|
|
@ -1001,13 +1145,13 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (var attr in cascadeRemove) {
|
for (var attr in cascadeRemove) {
|
||||||
_loop_9(attr);
|
_loop_7(attr);
|
||||||
}
|
}
|
||||||
if (hasAllEntity) {
|
if (hasAllEntity) {
|
||||||
var attributes = schema[entity].attributes;
|
var attributes = schema[entity].attributes;
|
||||||
var ref = attributes.entity.ref;
|
var ref = attributes.entity.ref;
|
||||||
var restEntities = (0, lodash_1.difference)(ref, entitiesOnEntityAttr);
|
var restEntities = (0, lodash_1.difference)(ref, entitiesOnEntityAttr);
|
||||||
var _loop_10 = function (e) {
|
var _loop_8 = function (e) {
|
||||||
checkers.push({
|
checkers.push({
|
||||||
entity: e,
|
entity: e,
|
||||||
action: 'remove',
|
action: 'remove',
|
||||||
|
|
@ -1043,7 +1187,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
try {
|
try {
|
||||||
for (var restEntities_1 = (e_8 = void 0, tslib_1.__values(restEntities)), restEntities_1_1 = restEntities_1.next(); !restEntities_1_1.done; restEntities_1_1 = restEntities_1.next()) {
|
for (var restEntities_1 = (e_8 = void 0, tslib_1.__values(restEntities)), restEntities_1_1 = restEntities_1.next(); !restEntities_1_1.done; restEntities_1_1 = restEntities_1.next()) {
|
||||||
var e = restEntities_1_1.value;
|
var e = restEntities_1_1.value;
|
||||||
_loop_10(e);
|
_loop_8(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
||||||
|
|
@ -1058,7 +1202,7 @@ function createRemoveCheckers(schema, authDict) {
|
||||||
};
|
};
|
||||||
// 注入声明的cascade删除时的外键处理动作
|
// 注入声明的cascade删除时的外键处理动作
|
||||||
for (var entity in authDict) {
|
for (var entity in authDict) {
|
||||||
_loop_6(entity);
|
_loop_4(entity);
|
||||||
}
|
}
|
||||||
return checkers;
|
return checkers;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,14 @@ export declare type Text = string;
|
||||||
export declare type Image = string;
|
export declare type Image = string;
|
||||||
export declare type File = string;
|
export declare type File = string;
|
||||||
export declare type Datetime = number | Date;
|
export declare type Datetime = number | Date;
|
||||||
|
export declare type Day = number | Date;
|
||||||
|
export declare type Time = number | Date;
|
||||||
export declare type Boolean = boolean;
|
export declare type Boolean = boolean;
|
||||||
|
export declare type Price = number;
|
||||||
export declare type PrimaryKey = string;
|
export declare type PrimaryKey = string;
|
||||||
export declare type ForeignKey<E extends string> = string;
|
export declare type ForeignKey<E extends string> = string;
|
||||||
export declare type Sequence = string;
|
export declare type Sequence = string;
|
||||||
export { Geo, SingleGeo } from './Geo';
|
export { Geo, SingleGeo } from './Geo';
|
||||||
export declare type DataTypes = number | string | Datetime | Geo | Object | SingleGeo;
|
export declare type DataTypes = number | string | Datetime | Day | Time | Geo | Object | SingleGeo;
|
||||||
export declare const types: string[];
|
export declare const types: string[];
|
||||||
export declare const unIndexedTypes: string[];
|
export declare const unIndexedTypes: string[];
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.unIndexedTypes = exports.types = void 0;
|
exports.unIndexedTypes = exports.types = void 0;
|
||||||
exports.types = ['Int', 'Uint', 'Double', 'Float', 'String', 'Text', 'Datetime', 'Boolean', 'Image', 'File', 'Geo', 'SingleGeo'];
|
exports.types = ['Int', 'Uint', 'Double', 'Float', 'String', 'Text', 'Datetime', 'Day', 'Time',
|
||||||
|
'Boolean', 'Image', 'File', 'Geo', 'SingleGeo', 'Price'];
|
||||||
exports.unIndexedTypes = ['Text', 'Image', 'File', 'Object'];
|
exports.unIndexedTypes = ['Text', 'Image', 'File', 'Object'];
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ declare type LocaleOfValue<V extends Record<string, string>> = {
|
||||||
};
|
};
|
||||||
export declare type LocaleDef<Sc extends Record<string, any>, Ac extends string, R extends string, V extends Record<string, string>> = {
|
export declare type LocaleDef<Sc extends Record<string, any>, Ac extends string, R extends string, V extends Record<string, string>> = {
|
||||||
[L in Language]?: {
|
[L in Language]?: {
|
||||||
|
name: string;
|
||||||
attr: LocaleOfSchema<Sc> & {
|
attr: LocaleOfSchema<Sc> & {
|
||||||
[A in keyof V]: string;
|
[A in keyof V]: string;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { EntityDict } from './Entity';
|
||||||
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
|
declare type ThemeColor = 'default' | 'success' | 'warning' | 'error';
|
||||||
|
export declare type ColorDict<ED extends BaseEntityDict & EntityDict> = {
|
||||||
|
[T in keyof ED]?: {
|
||||||
|
[A in keyof ED[T]['OpSchema']]?: {
|
||||||
|
[E in ED[T]['OpSchema'][A]]?: ThemeColor | `#${string}`;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export {};
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
import { RecurrenceRule, RecurrenceSpecDateRange, RecurrenceSpecObjLit } from 'node-schedule';
|
||||||
import { EntityDict } from './Entity';
|
import { EntityDict } from './Entity';
|
||||||
import { AsyncContext } from "../store/AsyncRowStore";
|
import { AsyncContext } from '../store/AsyncRowStore';
|
||||||
declare type RoutineFn<ED extends EntityDict, Cxt extends AsyncContext<ED>> = (context: Cxt) => Promise<string>;
|
declare type RoutineFn<ED extends EntityDict, Cxt extends AsyncContext<ED>> = (context: Cxt) => Promise<string>;
|
||||||
export declare type Routine<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
export declare type Routine<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -7,7 +8,7 @@ export declare type Routine<ED extends EntityDict, Cxt extends AsyncContext<ED>>
|
||||||
};
|
};
|
||||||
export declare type Timer<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
export declare type Timer<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
||||||
name: string;
|
name: string;
|
||||||
cron: string;
|
cron: RecurrenceRule | RecurrenceSpecDateRange | RecurrenceSpecObjLit | Date | string | number;
|
||||||
fn: RoutineFn<ED, Cxt>;
|
fn: RoutineFn<ED, Cxt>;
|
||||||
};
|
};
|
||||||
export {};
|
export {};
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@ export * from './Connector';
|
||||||
export * from './Timer';
|
export * from './Timer';
|
||||||
export * from './Port';
|
export * from './Port';
|
||||||
export * from './Endpoint';
|
export * from './Endpoint';
|
||||||
|
export * from './Style';
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,4 @@ tslib_1.__exportStar(require("./Connector"), exports);
|
||||||
tslib_1.__exportStar(require("./Timer"), exports);
|
tslib_1.__exportStar(require("./Timer"), exports);
|
||||||
tslib_1.__exportStar(require("./Port"), exports);
|
tslib_1.__exportStar(require("./Port"), exports);
|
||||||
tslib_1.__exportStar(require("./Endpoint"), exports);
|
tslib_1.__exportStar(require("./Endpoint"), exports);
|
||||||
|
tslib_1.__exportStar(require("./Style"), exports);
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,6 @@ export interface DataTypeParams {
|
||||||
precision?: number;
|
precision?: number;
|
||||||
scale?: number;
|
scale?: number;
|
||||||
signed?: boolean;
|
signed?: boolean;
|
||||||
|
max?: number;
|
||||||
|
min?: number;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ function makeContentTypeAndBody(data) {
|
||||||
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
||||||
if (data instanceof FormData) {
|
if (data instanceof FormData) {
|
||||||
return {
|
return {
|
||||||
contentType: 'multipart/form-data',
|
// contentType: 'multipart/form-data',
|
||||||
body: data,
|
body: data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -39,11 +39,12 @@ var SimpleConnector = /** @class */ (function (_super) {
|
||||||
_a = makeContentTypeAndBody(params), contentType = _a.contentType, body = _a.body;
|
_a = makeContentTypeAndBody(params), contentType = _a.contentType, body = _a.body;
|
||||||
return [4 /*yield*/, global.fetch(this.serverUrl, {
|
return [4 /*yield*/, global.fetch(this.serverUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: Object.assign({
|
||||||
'Content-Type': contentType,
|
|
||||||
'oak-cxt': cxtStr,
|
'oak-cxt': cxtStr,
|
||||||
'oak-aspect': name,
|
'oak-aspect': name,
|
||||||
},
|
}, contentType && {
|
||||||
|
'Content-Type': contentType,
|
||||||
|
}),
|
||||||
body: body,
|
body: body,
|
||||||
})];
|
})];
|
||||||
case 1:
|
case 1:
|
||||||
|
|
@ -106,7 +107,7 @@ var SimpleConnector = /** @class */ (function (_super) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
SimpleConnector.prototype.serializeResult = function (result, context, headers, body) {
|
SimpleConnector.prototype.serializeResult = function (result, context, headers, body) {
|
||||||
if (result instanceof stream_1.Stream) {
|
if (result instanceof stream_1.Stream || result instanceof Buffer) {
|
||||||
return {
|
return {
|
||||||
body: result,
|
body: result,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export declare function schedule(cron: string, fn: (date: Date) => any): void;
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.schedule = void 0;
|
|
||||||
var tslib_1 = require("tslib");
|
|
||||||
var cronjs_matcher_1 = require("@datasert/cronjs-matcher");
|
|
||||||
var dayjs_1 = tslib_1.__importDefault(require("dayjs"));
|
|
||||||
function schedule(cron, fn) {
|
|
||||||
var futureMatches = (0, cronjs_matcher_1.getFutureMatches)(cron, {
|
|
||||||
matchCount: 1,
|
|
||||||
});
|
|
||||||
var date = (0, dayjs_1.default)(futureMatches[0]);
|
|
||||||
var interval = date.diff((0, dayjs_1.default)(), 'ms');
|
|
||||||
setTimeout(function () {
|
|
||||||
fn(new Date());
|
|
||||||
schedule(cron, fn);
|
|
||||||
}, interval);
|
|
||||||
}
|
|
||||||
exports.schedule = schedule;
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
declare const maskIdCard: (idCardNumber: string) => string;
|
||||||
|
declare const maskMobile: (mobile: string) => string;
|
||||||
|
declare const maskName: (name: string) => string;
|
||||||
|
declare const maskStar: (str: string, front: number, end: number, star: string) => string;
|
||||||
|
export { maskIdCard, maskMobile, maskName, maskStar, };
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.maskStar = exports.maskName = exports.maskMobile = exports.maskIdCard = void 0;
|
||||||
|
var maskIdCard = function (idCardNumber) {
|
||||||
|
if (!idCardNumber instanceof String) {
|
||||||
|
throw new Error("身份证号码必须是String类型");
|
||||||
|
}
|
||||||
|
var begin = idCardNumber.slice(0, 4);
|
||||||
|
var end = idCardNumber.slice(idCardNumber.length - 4, 4);
|
||||||
|
for (var i = 0; i < idCardNumber.length - 8; i++) {
|
||||||
|
begin = begin.concat("*");
|
||||||
|
}
|
||||||
|
return begin.concat(end);
|
||||||
|
};
|
||||||
|
exports.maskIdCard = maskIdCard;
|
||||||
|
var maskMobile = function (mobile) {
|
||||||
|
var begin = mobile.slice(0, 3);
|
||||||
|
var end = mobile.slice(7, 11);
|
||||||
|
return begin.concat("****").concat(end);
|
||||||
|
};
|
||||||
|
exports.maskMobile = maskMobile;
|
||||||
|
var maskName = function (name) {
|
||||||
|
return name.slice(0, name.length - 1).concat("*");
|
||||||
|
};
|
||||||
|
exports.maskName = maskName;
|
||||||
|
var maskStar = function (str, frontLen, endLen, star) {
|
||||||
|
if (star === void 0) { star = '*'; }
|
||||||
|
var len = str.length - frontLen - endLen;
|
||||||
|
var xing = '';
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
xing += star;
|
||||||
|
}
|
||||||
|
return str.substring(0, frontLen) + xing + str.substring(str.length - endLen);
|
||||||
|
};
|
||||||
|
exports.maskStar = maskStar;
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
declare const ToCent: (float: number) => number;
|
||||||
|
declare const ToYuan: (int: number) => number;
|
||||||
|
declare const StringToCent: (value: string, allowNegative?: true) => number | undefined;
|
||||||
|
declare const CentToString: (value: number) => string | undefined;
|
||||||
|
export { ToCent, ToYuan, StringToCent, CentToString, };
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.CentToString = exports.StringToCent = exports.ToYuan = exports.ToCent = void 0;
|
||||||
|
var ToCent = function (float) {
|
||||||
|
return Math.round(float * 100);
|
||||||
|
};
|
||||||
|
exports.ToCent = ToCent;
|
||||||
|
var ToYuan = function (int) {
|
||||||
|
return Math.round(int) / 100;
|
||||||
|
};
|
||||||
|
exports.ToYuan = ToYuan;
|
||||||
|
var StringToCent = function (value, allowNegative) {
|
||||||
|
var numValue = parseInt(value, 10);
|
||||||
|
if (typeof numValue === 'number' && (numValue >= 0 || allowNegative)) {
|
||||||
|
return ToCent(numValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.StringToCent = StringToCent;
|
||||||
|
var CentToString = function (value) {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return "".concat(ToYuan(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.CentToString = CentToString;
|
||||||
|
|
@ -16,6 +16,7 @@ export declare const isNickname: ValidatorFunction;
|
||||||
export declare const isSizedCaptcha: ValidatorFunction;
|
export declare const isSizedCaptcha: ValidatorFunction;
|
||||||
export declare const isDigital: ValidatorFunction;
|
export declare const isDigital: ValidatorFunction;
|
||||||
export declare const isPhone: ValidatorFunction;
|
export declare const isPhone: ValidatorFunction;
|
||||||
|
export declare const isTel: ValidatorFunction;
|
||||||
export declare const isNumber: ValidatorFunction;
|
export declare const isNumber: ValidatorFunction;
|
||||||
export declare const isMoney: ValidatorMoneyFunction;
|
export declare const isMoney: ValidatorMoneyFunction;
|
||||||
export declare const isVehicleNumber: ValidatorFunction;
|
export declare const isVehicleNumber: ValidatorFunction;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.checkAttributesScope = exports.checkAttributesNotNull = exports.isVehicleNumber = exports.isMoney = exports.isNumber = exports.isPhone = exports.isDigital = exports.isSizedCaptcha = exports.isNickname = exports.isUrl = exports.isSoldierNumber = exports.isBirthNumber = exports.isTwCardNumber = exports.isAmCardNumber = exports.isHkCardNumber = exports.isPassportNumber = exports.isIdCardNumber = exports.isCaptcha = exports.isPassword = exports.isMobile = void 0;
|
exports.checkAttributesScope = exports.checkAttributesNotNull = exports.isVehicleNumber = exports.isMoney = exports.isNumber = exports.isTel = exports.isPhone = exports.isDigital = exports.isSizedCaptcha = exports.isNickname = exports.isUrl = exports.isSoldierNumber = exports.isBirthNumber = exports.isTwCardNumber = exports.isAmCardNumber = exports.isHkCardNumber = exports.isPassportNumber = exports.isIdCardNumber = exports.isCaptcha = exports.isPassword = exports.isMobile = void 0;
|
||||||
var types_1 = require("../types");
|
var types_1 = require("../types");
|
||||||
var isMobile = function (text) {
|
var isMobile = function (text) {
|
||||||
return ((text) && (typeof text === "string") && ((/^1[3|4|5|6|7|8|9]\d{9}$/.test(text))));
|
return ((text) && (typeof text === "string") && ((/^1[3|4|5|6|7|8|9]\d{9}$/.test(text))));
|
||||||
|
|
@ -79,14 +79,19 @@ var isPhone = function (phone) {
|
||||||
return /^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$/.test(phone);
|
return /^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$/.test(phone);
|
||||||
};
|
};
|
||||||
exports.isPhone = isPhone;
|
exports.isPhone = isPhone;
|
||||||
|
var isTel = function (text) {
|
||||||
|
// 1、133xxxx4545 2、0571-630xx239 3、400-123-1400
|
||||||
|
var reg = /^(((\d{3,4}-)?[0-9]{7,8})|(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}|((400)-(\d{3})-(\d{4})(.)(\d{1,4})|(400)-(\d{3})-(\d{4}$)|(400)(\d{3})(\d{4}$)|(400)-(\d{4})-(\d{3}$)))$/.test(text);
|
||||||
|
return reg;
|
||||||
|
};
|
||||||
|
exports.isTel = isTel;
|
||||||
var isNumber = function (str) {
|
var isNumber = function (str) {
|
||||||
return /^[0-9]*$/.test(str);
|
return /^[0-9]*$/.test(str);
|
||||||
};
|
};
|
||||||
exports.isNumber = isNumber;
|
exports.isNumber = isNumber;
|
||||||
var isMoney = function (str, zero) {
|
var isMoney = function (str, zero) {
|
||||||
// zero为true包含零
|
// 金额,最多可以有两位小数 zero为true包含零
|
||||||
if (zero) {
|
if (zero) {
|
||||||
// 金额,最多可以有两位小数
|
|
||||||
return /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(str);
|
return /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(str);
|
||||||
}
|
}
|
||||||
return /(^[1-9](\d+)?(\.\d{1,2})?$)|(^\d\.\d{1,2}$)/.test(str);
|
return /(^[1-9](\d+)?(\.\d{1,2})?$)|(^\d\.\d{1,2}$)/.test(str);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "oak-domain",
|
"name": "oak-domain",
|
||||||
"version": "2.6.3",
|
"version": "2.6.4",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "XuChang"
|
"name": "XuChang"
|
||||||
},
|
},
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
"@types/luxon": "^2.0.9",
|
"@types/luxon": "^2.0.9",
|
||||||
"@types/mocha": "^8.2.0",
|
"@types/mocha": "^8.2.0",
|
||||||
"@types/node": "^14.14.25",
|
"@types/node": "^14.14.25",
|
||||||
|
"@types/node-schedule": "^2.1.0",
|
||||||
"@types/react": "^17.0.2",
|
"@types/react": "^17.0.2",
|
||||||
"@types/uuid": "^8.3.0",
|
"@types/uuid": "^8.3.0",
|
||||||
"@types/wechat-miniprogram": "^3.4.1",
|
"@types/wechat-miniprogram": "^3.4.1",
|
||||||
|
|
@ -40,9 +41,9 @@
|
||||||
"typescript": "^4.7.4"
|
"typescript": "^4.7.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@datasert/cronjs-matcher": "^1.2.0",
|
|
||||||
"dayjs": "^1.11.5",
|
"dayjs": "^1.11.5",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"node-schedule": "^2.1.1",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1642,7 +1642,8 @@ function constructFilter(statements: Array<ts.Statement>, entity: string) {
|
||||||
case 'Int':
|
case 'Int':
|
||||||
case 'Uint':
|
case 'Uint':
|
||||||
case 'Float':
|
case 'Float':
|
||||||
case 'Double': {
|
case 'Double':
|
||||||
|
case 'Price': {
|
||||||
type2 = factory.createTypeReferenceNode(
|
type2 = factory.createTypeReferenceNode(
|
||||||
factory.createIdentifier('Q_NumberValue'),
|
factory.createIdentifier('Q_NumberValue'),
|
||||||
);
|
);
|
||||||
|
|
@ -1897,7 +1898,8 @@ function constructProjection(statements: Array<ts.Statement>, entity: string) {
|
||||||
case 'File':
|
case 'File':
|
||||||
case 'SingleGeo':
|
case 'SingleGeo':
|
||||||
case 'Geo':
|
case 'Geo':
|
||||||
case 'Object': {
|
case 'Object':
|
||||||
|
case 'Price': {
|
||||||
properties.push(
|
properties.push(
|
||||||
[name, false]
|
[name, false]
|
||||||
)
|
)
|
||||||
|
|
@ -2410,7 +2412,8 @@ function constructSorter(statements: Array<ts.Statement>, entity: string) {
|
||||||
case 'Boolean':
|
case 'Boolean':
|
||||||
case 'Datetime':
|
case 'Datetime':
|
||||||
case 'Image':
|
case 'Image':
|
||||||
case 'File': {
|
case 'File':
|
||||||
|
case 'Price': {
|
||||||
type2 = factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
|
type2 = factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -4417,6 +4420,11 @@ const initialStatements = () => [
|
||||||
undefined,
|
undefined,
|
||||||
factory.createIdentifier('File')
|
factory.createIdentifier('File')
|
||||||
),
|
),
|
||||||
|
factory.createImportSpecifier(
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
factory.createIdentifier('Price')
|
||||||
|
),
|
||||||
factory.createImportSpecifier(
|
factory.createImportSpecifier(
|
||||||
false,
|
false,
|
||||||
undefined,
|
undefined,
|
||||||
|
|
@ -5332,40 +5340,16 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'Float': {
|
case 'Double':
|
||||||
attrAssignments.push(
|
case 'Float':
|
||||||
factory.createPropertyAssignment(
|
case 'Decimal': {
|
||||||
factory.createIdentifier("type"),
|
if (['Double', 'Float'].includes(text)) {
|
||||||
factory.createStringLiteral("float")
|
console.warn(`${entity}对象中还有${text}类型定义,现在统一用Decimal进行存储`);
|
||||||
),
|
|
||||||
factory.createPropertyAssignment(
|
|
||||||
factory.createIdentifier("params"),
|
|
||||||
factory.createObjectLiteralExpression(
|
|
||||||
[
|
|
||||||
factory.createPropertyAssignment(
|
|
||||||
factory.createIdentifier("precision"),
|
|
||||||
factory.createNumericLiteral(
|
|
||||||
(<ts.NumericLiteral>(<ts.LiteralTypeNode>typeArguments![0]).literal).text
|
|
||||||
)
|
|
||||||
),
|
|
||||||
factory.createPropertyAssignment(
|
|
||||||
factory.createIdentifier("scale"),
|
|
||||||
factory.createNumericLiteral(
|
|
||||||
(<ts.NumericLiteral>(<ts.LiteralTypeNode>typeArguments![1]).literal).text
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 'Double': {
|
|
||||||
attrAssignments.push(
|
attrAssignments.push(
|
||||||
factory.createPropertyAssignment(
|
factory.createPropertyAssignment(
|
||||||
factory.createIdentifier("type"),
|
factory.createIdentifier("type"),
|
||||||
factory.createStringLiteral("double")
|
factory.createStringLiteral("decimal")
|
||||||
),
|
),
|
||||||
factory.createPropertyAssignment(
|
factory.createPropertyAssignment(
|
||||||
factory.createIdentifier("params"),
|
factory.createIdentifier("params"),
|
||||||
|
|
@ -5399,6 +5383,15 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'Price': {
|
||||||
|
attrAssignments.push(
|
||||||
|
factory.createPropertyAssignment(
|
||||||
|
factory.createIdentifier("type"),
|
||||||
|
factory.createStringLiteral("money")
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'Datetime': {
|
case 'Datetime': {
|
||||||
attrAssignments.push(
|
attrAssignments.push(
|
||||||
factory.createPropertyAssignment(
|
factory.createPropertyAssignment(
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ const locale: LocaleDef<Schema, Action, '', {
|
||||||
iState: IState,
|
iState: IState,
|
||||||
}> = {
|
}> = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '更新',
|
||||||
attr: {
|
attr: {
|
||||||
targetEntity: '目标对象',
|
targetEntity: '目标对象',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ const config: Configuration = {
|
||||||
|
|
||||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '更新对象连接',
|
||||||
attr: {
|
attr: {
|
||||||
modi: '更新',
|
modi: '更新',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ const configuration: Configuration = {
|
||||||
|
|
||||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '操作',
|
||||||
attr: {
|
attr: {
|
||||||
action: '动作',
|
action: '动作',
|
||||||
data: '数据',
|
data: '数据',
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ const config: Configuration = {
|
||||||
|
|
||||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '操作对象连接',
|
||||||
attr: {
|
attr: {
|
||||||
oper: '操作',
|
oper: '操作',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ const locale: LocaleDef<Schema, Action, '', {
|
||||||
userState: UserState;
|
userState: UserState;
|
||||||
}> = {
|
}> = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '用户',
|
||||||
attr: {
|
attr: {
|
||||||
name: '姓名',
|
name: '姓名',
|
||||||
nickname: '昵称',
|
nickname: '昵称',
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ const locale: LocaleDef<
|
||||||
{}
|
{}
|
||||||
> = {
|
> = {
|
||||||
zh_CN: {
|
zh_CN: {
|
||||||
|
name: '用户授权',
|
||||||
attr: {
|
attr: {
|
||||||
relation: '关系',
|
relation: '关系',
|
||||||
entity: '关联对象',
|
entity: '关联对象',
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,11 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
||||||
if (this.uuid) {
|
if (this.uuid) {
|
||||||
await this.rowStore.commit(this.uuid!);
|
await this.rowStore.commit(this.uuid!);
|
||||||
this.uuid = undefined;
|
this.uuid = undefined;
|
||||||
for(const e of this.events.commit) {
|
const { commit: commitEvents } = this.events;
|
||||||
|
this.resetEvents();
|
||||||
|
for (const e of commitEvents) {
|
||||||
await e();
|
await e();
|
||||||
}
|
}
|
||||||
this.resetEvents();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async rollback(): Promise<void> {
|
async rollback(): Promise<void> {
|
||||||
|
|
@ -81,10 +82,11 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
||||||
await this.rowStore.rollback(this.uuid!);
|
await this.rowStore.rollback(this.uuid!);
|
||||||
// console.log('rollback', this.uuid);
|
// console.log('rollback', this.uuid);
|
||||||
this.uuid = undefined;
|
this.uuid = undefined;
|
||||||
for(const e of this.events.rollback) {
|
const { rollback: rollbackEvents } = this.events;
|
||||||
|
this.resetEvents();
|
||||||
|
for (const e of rollbackEvents) {
|
||||||
await e();
|
await e();
|
||||||
}
|
}
|
||||||
this.resetEvents();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -220,12 +220,22 @@ export function translateCheckerInSyncContext<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FilterMakeFn<ED extends EntityDict & BaseEntityDict> = (operation: ED[keyof ED]['Operation'] | ED[keyof ED]['Selection'], userId: string) => ED[keyof ED]['Selection']['filter'] | {
|
type CreateRelationSingleCounter<ED extends EntityDict & BaseEntityDict> = {
|
||||||
$entity: keyof ED;
|
$entity: keyof ED;
|
||||||
$filter?: ED[keyof ED]['Selection']['filter'];
|
$filter?: ED[keyof ED]['Selection']['filter'];
|
||||||
$count?: number;
|
$count?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CreateRelationMultipleCounter<ED extends EntityDict & BaseEntityDict> = {
|
||||||
|
[K in '$$and' | '$$or']?: (CreateRelationSingleCounter<ED> | CreateRelationMultipleCounter<ED>)[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateRelationCounter<ED extends EntityDict & BaseEntityDict> = CreateRelationSingleCounter<ED> | CreateRelationMultipleCounter<ED>;
|
||||||
|
|
||||||
|
|
||||||
|
type FilterMakeFn<ED extends EntityDict & BaseEntityDict> =
|
||||||
|
(operation: ED[keyof ED]['Operation'] | ED[keyof ED]['Selection'], userId: string) => ED[keyof ED]['Selection']['filter'] | CreateRelationCounter<ED>;
|
||||||
|
|
||||||
function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityDict>(
|
function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityDict>(
|
||||||
schema: StorageSchema<ED>,
|
schema: StorageSchema<ED>,
|
||||||
lch: CascadeRelationItem,
|
lch: CascadeRelationItem,
|
||||||
|
|
@ -315,12 +325,18 @@ function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityD
|
||||||
|
|
||||||
const filterMaker = paths.length ? translateFilterMakerIter(entity2, 0) : translateRelationFilter(entity2);
|
const filterMaker = paths.length ? translateFilterMakerIter(entity2, 0) : translateRelationFilter(entity2);
|
||||||
if (!paths.length) {
|
if (!paths.length) {
|
||||||
|
// 不可能是create
|
||||||
return (oper, userId) => filterMaker(userId);
|
return (oper, userId) => filterMaker(userId);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 针对第一层做一下特别优化,比如对象A指向对象B(多对一),如果A的cascadePath是 'B',
|
* 针对第一层做一下特别优化,比如对象A指向对象B(多对一),如果A的cascadePath是 'B',
|
||||||
* 当create A时,会带有Bid。此时生成该B对象上的相关表达式查询返回,可以避免必须将此判定在对象创建之后再做
|
* 当create A时,会带有Bid。此时生成该B对象上的相关表达式查询返回,可以避免必须将此判定在对象创建之后再做
|
||||||
* 另一使用场景是,在查询A时,如果带有Bid(在对象跳一对多子对象场景下很常见),可以提前判定这个查询对某些用户一定返回空集
|
* 另一使用场景是,在查询A时,如果带有Bid(在对象跳一对多子对象场景下很常见),可以提前判定这个查询对某些用户一定返回空集
|
||||||
|
*
|
||||||
|
* 20230306:
|
||||||
|
* 在前台的权限判断中,会将list上的filter当成内在的限制对create动作进行判断,此时有一种可能是,filter并不能直接判断出外键,但会限制外键的查询范围。
|
||||||
|
* 例如,在jichuang项目中,就存在park/list上,平台的用户去访问时,其查询条件是{ system: { platformId: 1 }};而用户的关系落在system.platform.platformProvider上,
|
||||||
|
* 此时如直接通过data上的外键判断就会失败,需要通过对filter上相应的语义解构,进行进一步的判断
|
||||||
*/
|
*/
|
||||||
const [attr] = paths;
|
const [attr] = paths;
|
||||||
const relation = judgeRelation(schema, entity2, attr);
|
const relation = judgeRelation(schema, entity2, attr);
|
||||||
|
|
@ -328,14 +344,92 @@ function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityD
|
||||||
const filterMaker2 = paths.length > 1
|
const filterMaker2 = paths.length > 1
|
||||||
? (relation === 2 ? translateFilterMakerIter(attr, 1) : translateFilterMakerIter(relation, 1))
|
? (relation === 2 ? translateFilterMakerIter(attr, 1) : translateFilterMakerIter(relation, 1))
|
||||||
: (relation === 2 ? translateRelationFilter(attr) : translateRelationFilter(relation));
|
: (relation === 2 ? translateRelationFilter(attr) : translateRelationFilter(relation));
|
||||||
|
|
||||||
|
const translateCreateFilterMaker = (
|
||||||
|
entity: keyof ED,
|
||||||
|
filter: ED[keyof ED]['Selection']['filter'],
|
||||||
|
userId: string
|
||||||
|
): CreateRelationCounter<ED> | OakUserUnpermittedException<ED> => {
|
||||||
|
const counters: CreateRelationCounter<ED>[] = [];
|
||||||
|
if (filter) {
|
||||||
|
if (relation === 2) {
|
||||||
|
if (filter.entity === entity && filter.entityId) {
|
||||||
|
// 这里对entityId的限定的数据只要和userId有一条relation,就不能否定可能会有创建动作(外键在最终create时,data上一定会有判定)
|
||||||
|
counters.push({
|
||||||
|
$entity: attr,
|
||||||
|
$filter: addFilterSegment(filterMaker2(userId), { id: filter.entityId }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (filter[attr]) {
|
||||||
|
counters.push({
|
||||||
|
$entity: attr,
|
||||||
|
$filter: addFilterSegment(filterMaker2(userId), filter[attr]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(typeof relation === 'string');
|
||||||
|
if (filter[`${attr}Id`]) {
|
||||||
|
const filterMaker3 = paths.length > 1 ? translateFilterMakerIter(relation, 1) : translateRelationFilter(relation);
|
||||||
|
// 这里对attrId的限定的数据只要和userId有一条relation,就不能否定可能会有创建动作(外键在最终create时,data上一定会有判定)
|
||||||
|
counters.push({
|
||||||
|
$entity: relation,
|
||||||
|
$filter: addFilterSegment(filterMaker3(userId), { id: filter[`${attr}Id`] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (filter[attr]) {
|
||||||
|
counters.push({
|
||||||
|
$entity: relation,
|
||||||
|
$filter: addFilterSegment(filterMaker2(userId), filter[attr]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.$and) {
|
||||||
|
const countersAnd = filter.$and.map(
|
||||||
|
(ele: ED[keyof ED]['Selection']['filter']) => translateCreateFilterMaker(entity, ele, userId)
|
||||||
|
) as ReturnType<typeof translateCreateFilterMaker>[];
|
||||||
|
// and 只要有一个满足就行
|
||||||
|
const ca2 = countersAnd.filter(
|
||||||
|
ele => !(ele instanceof OakUserUnpermittedException)
|
||||||
|
) as CreateRelationCounter<ED>[];
|
||||||
|
counters.push(...ca2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.$or) {
|
||||||
|
const countersOr = filter.$and.map(
|
||||||
|
(ele: ED[keyof ED]['Selection']['filter']) => translateCreateFilterMaker(entity, ele, userId)
|
||||||
|
) as ReturnType<typeof translateCreateFilterMaker>[];
|
||||||
|
// or也只要有一个满足就行(不能否定)
|
||||||
|
const co2 = countersOr.filter(
|
||||||
|
ele => !(ele instanceof OakUserUnpermittedException)
|
||||||
|
) as CreateRelationCounter<ED>[];
|
||||||
|
counters.push(...co2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (counters.length === 0) {
|
||||||
|
// 一个counter都找不出来,说明当前路径上不满足
|
||||||
|
return new OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
else if (counters.length === 1) {
|
||||||
|
return counters[0];
|
||||||
|
}
|
||||||
|
// 是or关系,只要其中有一个满足就可以通过
|
||||||
|
return {
|
||||||
|
$$or: counters,
|
||||||
|
};
|
||||||
|
};
|
||||||
return (operation, userId) => {
|
return (operation, userId) => {
|
||||||
const { action } = operation as ED[keyof ED]['Operation'];
|
const { action } = operation as ED[keyof ED]['Operation'];
|
||||||
if (action === 'create') {
|
if (action === 'create') {
|
||||||
const { data } = operation as ED[keyof ED]['Create'];
|
const { data } = operation as ED[keyof ED]['Create'];
|
||||||
|
if (data) {
|
||||||
|
// 有data的情形根据data判定
|
||||||
const getForeignKeyId = (d: ED[keyof ED]['CreateSingle']['data']) => {
|
const getForeignKeyId = (d: ED[keyof ED]['CreateSingle']['data']) => {
|
||||||
if (relation === 2) {
|
if (relation === 2) {
|
||||||
if (d.entity === attr && typeof d.entityId === 'string') {
|
if (d.entity === attr && typeof d.entityId === 'string') {
|
||||||
return d.entitId as string;
|
return d.entityId as string;
|
||||||
}
|
}
|
||||||
throw new OakUserUnpermittedException();
|
throw new OakUserUnpermittedException();
|
||||||
}
|
}
|
||||||
|
|
@ -377,6 +471,19 @@ function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityD
|
||||||
$filter: addFilterSegment(filterMaker2(userId), { id: fkId }),
|
$filter: addFilterSegment(filterMaker2(userId), { id: fkId }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// todo
|
||||||
|
const { filter } = operation as ED[keyof ED]['Selection'];
|
||||||
|
if (filter) {
|
||||||
|
const counter = translateCreateFilterMaker(entity2, filter, userId);
|
||||||
|
if (counter instanceof OakUserUnpermittedException) {
|
||||||
|
throw counter;
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
throw new OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
const { filter } = operation;
|
const { filter } = operation;
|
||||||
if (relation === 2 && filter?.entity === attr && filter?.entityId) {
|
if (relation === 2 && filter?.entity === attr && filter?.entityId) {
|
||||||
if (typeof filter.entityId === 'string') {
|
if (typeof filter.entityId === 'string') {
|
||||||
|
|
@ -437,6 +544,93 @@ function translateActionAuthFilterMaker<ED extends EntityDict & BaseEntityDict>(
|
||||||
return filterMaker;
|
return filterMaker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execCreateCounter<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(
|
||||||
|
context: Cxt,
|
||||||
|
counter: CreateRelationCounter<ED>,
|
||||||
|
): SyncOrAsync<undefined | OakUserUnpermittedException<ED>> {
|
||||||
|
if ((<CreateRelationMultipleCounter<ED>>counter)?.$$and) {
|
||||||
|
// 每个counter都要满足才能过
|
||||||
|
const counters = (<CreateRelationMultipleCounter<ED>>counter)?.$$and!;
|
||||||
|
assert(counters.length > 0);
|
||||||
|
const counterResults = counters.map(
|
||||||
|
ele => execCreateCounter(context, ele)
|
||||||
|
);
|
||||||
|
if (counterResults[0] instanceof Promise) {
|
||||||
|
return Promise.all(counterResults)
|
||||||
|
.then(
|
||||||
|
(cr2) => {
|
||||||
|
const unpermitted = cr2.find(
|
||||||
|
(ele) => ele instanceof OakUserUnpermittedException
|
||||||
|
);
|
||||||
|
if (unpermitted) {
|
||||||
|
return unpermitted;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const unpermitted = counterResults.find(
|
||||||
|
(ele) => ele instanceof OakUserUnpermittedException
|
||||||
|
);
|
||||||
|
if (unpermitted) {
|
||||||
|
return unpermitted;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((<CreateRelationMultipleCounter<ED>>counter)?.$$or) {
|
||||||
|
// 只要有一个counter能过就算过
|
||||||
|
const counters = (<CreateRelationMultipleCounter<ED>>counter)?.$$or!;
|
||||||
|
assert(counters.length > 0);
|
||||||
|
const counterResults = counters.map(
|
||||||
|
ele => execCreateCounter(context, ele)
|
||||||
|
);
|
||||||
|
if (counterResults[0] instanceof Promise) {
|
||||||
|
return Promise.all(counterResults)
|
||||||
|
.then(
|
||||||
|
(cr2) => {
|
||||||
|
const permittedIdx = cr2.indexOf(undefined);
|
||||||
|
if (permittedIdx !== -1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return new OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const permittedIndex = counterResults.indexOf(undefined);
|
||||||
|
if (permittedIndex !== -1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((<CreateRelationSingleCounter<ED>>counter)?.$entity) {
|
||||||
|
const { $entity, $filter, $count = 1 } = counter as CreateRelationSingleCounter<ED>;
|
||||||
|
const count = context.count($entity, {
|
||||||
|
filter: $filter,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
if (count instanceof Promise) {
|
||||||
|
return count.then(
|
||||||
|
(c2) => {
|
||||||
|
if (c2 >= $count) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return new OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return count >= $count ? undefined : new OakUserUnpermittedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function makePotentialFilter<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(
|
function makePotentialFilter<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(
|
||||||
operation: ED[keyof ED]['Operation'] | ED[keyof ED]['Selection'],
|
operation: ED[keyof ED]['Operation'] | ED[keyof ED]['Selection'],
|
||||||
context: Cxt,
|
context: Cxt,
|
||||||
|
|
@ -466,30 +660,17 @@ function makePotentialFilter<ED extends EntityDict & BaseEntityDict, Cxt extends
|
||||||
let isAsyncOr = false;
|
let isAsyncOr = false;
|
||||||
for (const f of filters) {
|
for (const f of filters) {
|
||||||
if (f instanceof Array) {
|
if (f instanceof Array) {
|
||||||
let isAsyncAnd = true;
|
let isAsyncAnd = false;
|
||||||
|
assert(f.length > 0);
|
||||||
const filtersAnd: (SyncOrAsync<ED[keyof ED]['Selection']['filter'] | OakUserUnpermittedException<ED>>)[] = [];
|
const filtersAnd: (SyncOrAsync<ED[keyof ED]['Selection']['filter'] | OakUserUnpermittedException<ED>>)[] = [];
|
||||||
for (const ff of f) {
|
for (const ff of f) {
|
||||||
if (ff?.$entity) {
|
if ((<CreateRelationMultipleCounter<ED>>ff)?.$$and || (<CreateRelationMultipleCounter<ED>>ff)?.$$or || (<CreateRelationSingleCounter<ED>>ff)?.$entity) {
|
||||||
const { $entity, $filter, $count = 1 } = ff!;
|
// 每个counter都要满足才能过
|
||||||
const count = context.count($entity, {
|
const result = execCreateCounter<ED, Cxt>(context, ff as CreateRelationMultipleCounter<ED>);
|
||||||
filter: $filter,
|
if (result instanceof Promise) {
|
||||||
}, {});
|
|
||||||
if (count instanceof Promise) {
|
|
||||||
isAsyncAnd = true;
|
isAsyncAnd = true;
|
||||||
filtersAnd.push(
|
|
||||||
count.then(
|
|
||||||
(c2) => {
|
|
||||||
if (c2 >= $count) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return new OakUserUnpermittedException();
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filtersAnd.push(count >= $count ? undefined : new OakUserUnpermittedException());
|
|
||||||
}
|
}
|
||||||
|
filtersAnd.push(result);
|
||||||
}
|
}
|
||||||
else if (ff) {
|
else if (ff) {
|
||||||
filtersAnd.push(ff as ED[keyof ED]['Selection']['filter']);
|
filtersAnd.push(ff as ED[keyof ED]['Selection']['filter']);
|
||||||
|
|
@ -520,22 +701,12 @@ function makePotentialFilter<ED extends EntityDict & BaseEntityDict, Cxt extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (f?.$entity) {
|
if ((<CreateRelationMultipleCounter<ED>>f)?.$$and || (<CreateRelationMultipleCounter<ED>>f)?.$$or || (<CreateRelationSingleCounter<ED>>f)?.$entity) {
|
||||||
const { $entity, $filter, $count = 1 } = f!;
|
const counterResults = execCreateCounter<ED, Cxt>(context, f as CreateRelationCounter<ED>);
|
||||||
const count = context.count($entity, {
|
if (counterResults instanceof Promise) {
|
||||||
filter: $filter,
|
|
||||||
}, {});
|
|
||||||
if (count instanceof Promise) {
|
|
||||||
isAsyncOr = true;
|
isAsyncOr = true;
|
||||||
filtersOr.push(
|
|
||||||
count.then(
|
|
||||||
(c2) => c2 >= $count ? undefined : new OakUserUnpermittedException()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filtersOr.push(count >= $count ? undefined : new OakUserUnpermittedException());
|
|
||||||
}
|
}
|
||||||
|
filtersOr.push(counterResults);
|
||||||
}
|
}
|
||||||
else if (f) {
|
else if (f) {
|
||||||
filtersOr.push(f as ED[keyof ED]['Selection']['filter']);
|
filtersOr.push(f as ED[keyof ED]['Selection']['filter']);
|
||||||
|
|
@ -584,11 +755,26 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
||||||
if (relationAuth) {
|
if (relationAuth) {
|
||||||
const raFilterMakerDict = {} as Record<string, FilterMakeFn<ED> | (FilterMakeFn<ED> | FilterMakeFn<ED>[])[]>;
|
const raFilterMakerDict = {} as Record<string, FilterMakeFn<ED> | (FilterMakeFn<ED> | FilterMakeFn<ED>[])[]>;
|
||||||
const userEntityName = `user${firstLetterUpperCase(entity)}`;
|
const userEntityName = `user${firstLetterUpperCase(entity)}`;
|
||||||
|
const allAuthItem: (CascadeRelationItem | CascadeRelationItem[])[] = [];
|
||||||
for (const r in relationAuth) {
|
for (const r in relationAuth) {
|
||||||
|
const authItem = relationAuth[r as NonNullable<ED[keyof ED]['Relation']>]!;
|
||||||
Object.assign(raFilterMakerDict, {
|
Object.assign(raFilterMakerDict, {
|
||||||
[r]: translateActionAuthFilterMaker(schema, relationAuth[r as NonNullable<ED[keyof ED]['Relation']>]!, userEntityName, entity),
|
[r]: translateActionAuthFilterMaker(schema, authItem, userEntityName, entity),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (authItem instanceof Array) {
|
||||||
|
allAuthItem.push(...authItem);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
allAuthItem.push(authItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果不指定relation,则使用所有的authItem的or组合
|
||||||
|
Object.assign(raFilterMakerDict, {
|
||||||
|
'@@all': translateActionAuthFilterMaker(schema, allAuthItem, userEntityName, entity),
|
||||||
|
});
|
||||||
|
|
||||||
const entityIdAttr = `${entity}Id`;
|
const entityIdAttr = `${entity}Id`;
|
||||||
checkers.push({
|
checkers.push({
|
||||||
entity: userEntityName as keyof ED,
|
entity: userEntityName as keyof ED,
|
||||||
|
|
@ -598,8 +784,12 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
||||||
const { data } = operation as ED[keyof ED]['Create'];
|
const { data } = operation as ED[keyof ED]['Create'];
|
||||||
assert(!(data instanceof Array));
|
assert(!(data instanceof Array));
|
||||||
const { relation, [entityIdAttr]: entityId } = data;
|
const { relation, [entityIdAttr]: entityId } = data;
|
||||||
|
if (!relation) {
|
||||||
|
// 不指定relation测试是否有创建权限
|
||||||
|
return makePotentialFilter(operation, context, raFilterMakerDict['@@all']);
|
||||||
|
}
|
||||||
if (!raFilterMakerDict[relation]) {
|
if (!raFilterMakerDict[relation]) {
|
||||||
return;
|
throw new OakUserUnpermittedException();
|
||||||
}
|
}
|
||||||
const filter = makePotentialFilter(operation, context, raFilterMakerDict[relation]);
|
const filter = makePotentialFilter(operation, context, raFilterMakerDict[relation]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,17 @@ export type Text = string;
|
||||||
export type Image = string;
|
export type Image = string;
|
||||||
export type File = string;
|
export type File = string;
|
||||||
export type Datetime = number | Date;
|
export type Datetime = number | Date;
|
||||||
|
export type Day = number | Date;
|
||||||
|
export type Time = number | Date;
|
||||||
export type Boolean = boolean;
|
export type Boolean = boolean;
|
||||||
|
export type Price = number;
|
||||||
export type PrimaryKey = string;
|
export type PrimaryKey = string;
|
||||||
export type ForeignKey<E extends string> = string;
|
export type ForeignKey<E extends string> = string;
|
||||||
export type Sequence = string; // 自增长序列,为了让人阅读方便,为了支持分布式这里用string,底层实现可自定义
|
export type Sequence = string; // 自增长序列,为了让人阅读方便,为了支持分布式这里用string,底层实现可自定义
|
||||||
export { Geo, SingleGeo } from './Geo';
|
export { Geo, SingleGeo } from './Geo';
|
||||||
|
|
||||||
export type DataTypes = number | string | Datetime | Geo | Object | SingleGeo;
|
export type DataTypes = number | string | Datetime | Day | Time | Geo | Object | SingleGeo;
|
||||||
|
|
||||||
export const types = ['Int', 'Uint', 'Double', 'Float', 'String', 'Text', 'Datetime', 'Boolean', 'Image', 'File', 'Geo', 'SingleGeo'];
|
export const types = ['Int', 'Uint', 'Double', 'Float', 'String', 'Text', 'Datetime', 'Day', 'Time',
|
||||||
|
'Boolean', 'Image', 'File', 'Geo', 'SingleGeo', 'Price'];
|
||||||
export const unIndexedTypes = ['Text', 'Image', 'File', 'Object'];
|
export const unIndexedTypes = ['Text', 'Image', 'File', 'Object'];
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ type LocaleOfValue<V extends Record<string, string>> = {
|
||||||
|
|
||||||
export type LocaleDef<Sc extends Record<string, any>, Ac extends string, R extends string, V extends Record<string, string>> = {
|
export type LocaleDef<Sc extends Record<string, any>, Ac extends string, R extends string, V extends Record<string, string>> = {
|
||||||
[L in Language]?: {
|
[L in Language]?: {
|
||||||
|
name: string;
|
||||||
attr: LocaleOfSchema<Sc> & {
|
attr: LocaleOfSchema<Sc> & {
|
||||||
[A in keyof V]: string; // 目前写在V里面的应该只有枚举变量和state
|
[A in keyof V]: string; // 目前写在V里面的应该只有枚举变量和state
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { EntityDict } from './Entity';
|
||||||
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
|
|
||||||
|
type ThemeColor = 'default' | 'success' | 'warning' | 'error';
|
||||||
|
|
||||||
|
export type ColorDict<ED extends BaseEntityDict & EntityDict> = {
|
||||||
|
[T in keyof ED]?: {
|
||||||
|
[A in keyof ED[T]['OpSchema']]?: {
|
||||||
|
[E in ED[T]['OpSchema'][A]]?: ThemeColor | `#${string}`;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
import { RecurrenceRule, RecurrenceSpecDateRange, RecurrenceSpecObjLit } from 'node-schedule';
|
||||||
import { EntityDict } from './Entity';
|
import { EntityDict } from './Entity';
|
||||||
import { AsyncContext } from "../store/AsyncRowStore";
|
import { AsyncContext } from '../store/AsyncRowStore';
|
||||||
|
|
||||||
type RoutineFn<ED extends EntityDict, Cxt extends AsyncContext<ED>> = (context: Cxt) => Promise<string>;
|
type RoutineFn<ED extends EntityDict, Cxt extends AsyncContext<ED>> = (
|
||||||
|
context: Cxt
|
||||||
|
) => Promise<string>;
|
||||||
|
|
||||||
export type Routine<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
export type Routine<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -10,6 +13,6 @@ export type Routine<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
||||||
|
|
||||||
export type Timer<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
export type Timer<ED extends EntityDict, Cxt extends AsyncContext<ED>> = {
|
||||||
name: string;
|
name: string;
|
||||||
cron: string;
|
cron: RecurrenceRule | RecurrenceSpecDateRange | RecurrenceSpecObjLit | Date | string | number;
|
||||||
fn: RoutineFn<ED, Cxt>;
|
fn: RoutineFn<ED, Cxt>;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@ export * from './Connector';
|
||||||
export * from './Timer';
|
export * from './Timer';
|
||||||
export * from './Port';
|
export * from './Port';
|
||||||
export * from './Endpoint';
|
export * from './Endpoint';
|
||||||
|
export * from './Style';
|
||||||
|
|
|
||||||
|
|
@ -218,4 +218,6 @@ export interface DataTypeParams {
|
||||||
precision?: number;
|
precision?: number;
|
||||||
scale?: number;
|
scale?: number;
|
||||||
signed?: boolean;
|
signed?: boolean;
|
||||||
|
max?: number;
|
||||||
|
min?: number;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ function makeContentTypeAndBody(data: any) {
|
||||||
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
||||||
if (data instanceof FormData) {
|
if (data instanceof FormData) {
|
||||||
return {
|
return {
|
||||||
contentType: 'multipart/form-data',
|
// contentType: 'multipart/form-data',
|
||||||
body: data,
|
body: data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -41,11 +41,15 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
||||||
const { contentType, body } = makeContentTypeAndBody(params);
|
const { contentType, body } = makeContentTypeAndBody(params);
|
||||||
const response = await global.fetch(this.serverUrl, {
|
const response = await global.fetch(this.serverUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: Object.assign(
|
||||||
'Content-Type': contentType,
|
{
|
||||||
'oak-cxt': cxtStr,
|
'oak-cxt': cxtStr,
|
||||||
'oak-aspect': name as string,
|
'oak-aspect': name as string,
|
||||||
},
|
},
|
||||||
|
contentType && {
|
||||||
|
'Content-Type': contentType as string,
|
||||||
|
}
|
||||||
|
) as RequestInit['headers'],
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
if (response.status > 299) {
|
if (response.status > 299) {
|
||||||
|
|
@ -101,7 +105,7 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): { body: any; headers?: Record<string, any> | undefined; } {
|
serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): { body: any; headers?: Record<string, any> | undefined; } {
|
||||||
if (result instanceof Stream) {
|
if (result instanceof Stream || result instanceof Buffer) {
|
||||||
return {
|
return {
|
||||||
body: result,
|
body: result,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
import { getFutureMatches } from '@datasert/cronjs-matcher';
|
|
||||||
import DayJs from 'dayjs';
|
|
||||||
|
|
||||||
export function schedule(cron: string, fn: (date: Date) => any) {
|
|
||||||
const futureMatches = getFutureMatches(cron, {
|
|
||||||
matchCount: 1,
|
|
||||||
});
|
|
||||||
const date = DayJs(futureMatches[0]);
|
|
||||||
const interval = date.diff(DayJs(), 'ms');
|
|
||||||
setTimeout(
|
|
||||||
() => {
|
|
||||||
fn(new Date());
|
|
||||||
schedule(cron, fn);
|
|
||||||
},
|
|
||||||
interval
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
const maskIdCard: (idCardNumber: string) => string = (idCardNumber) => {
|
||||||
|
if(!idCardNumber as any instanceof String) {
|
||||||
|
throw new Error("身份证号码必须是String类型");
|
||||||
|
}
|
||||||
|
let begin = idCardNumber.slice(0, 4);
|
||||||
|
let end = idCardNumber.slice(idCardNumber.length - 4, 4);
|
||||||
|
for(let i = 0; i < idCardNumber.length - 8; i ++) {
|
||||||
|
begin = begin.concat("*");
|
||||||
|
}
|
||||||
|
return begin.concat(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
const maskMobile: (mobile: string) => string = (mobile) => {
|
||||||
|
let begin = mobile.slice(0, 3);
|
||||||
|
let end = mobile.slice(7, 11);
|
||||||
|
return begin.concat("****").concat(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const maskName: (name: string) => string = (name) => {
|
||||||
|
return name.slice(0, name.length - 1).concat("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
const maskStar: (str: string, front: number, end: number, star: string) => string = (str, frontLen, endLen, star = '*') => {
|
||||||
|
const len = str.length - frontLen - endLen;
|
||||||
|
let xing = '';
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
xing += star;
|
||||||
|
}
|
||||||
|
return str.substring(0, frontLen) + xing + str.substring(str.length - endLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export {
|
||||||
|
maskIdCard,
|
||||||
|
maskMobile,
|
||||||
|
maskName,
|
||||||
|
maskStar,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
const ToCent: (float: number) => number = (float) => {
|
||||||
|
return Math.round(float * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ToYuan: (int: number) => number = ( int) => {
|
||||||
|
return Math.round(int) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StringToCent: (value: string, allowNegative?: true) => number | undefined = (value, allowNegative) => {
|
||||||
|
const numValue = parseInt(value, 10);
|
||||||
|
if (typeof numValue === 'number' && (numValue >= 0 || allowNegative)) {
|
||||||
|
return ToCent(numValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CentToString: (value: number) => string | undefined = (value) => {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return `${ToYuan(value)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
ToCent,
|
||||||
|
ToYuan,
|
||||||
|
StringToCent,
|
||||||
|
CentToString,
|
||||||
|
}
|
||||||
|
|
@ -83,16 +83,26 @@ export const isPhone: ValidatorFunction = (phone) => {
|
||||||
return /^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$/.test(phone);
|
return /^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$/.test(phone);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isTel: ValidatorFunction = (text) => {
|
||||||
|
// 1、133xxxx4545 2、0571-630xx239 3、400-123-1400
|
||||||
|
const reg =
|
||||||
|
/^(((\d{3,4}-)?[0-9]{7,8})|(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}|((400)-(\d{3})-(\d{4})(.)(\d{1,4})|(400)-(\d{3})-(\d{4}$)|(400)(\d{3})(\d{4}$)|(400)-(\d{4})-(\d{3}$)))$/.test(
|
||||||
|
text
|
||||||
|
);
|
||||||
|
return reg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export const isNumber: ValidatorFunction = (str) => {
|
export const isNumber: ValidatorFunction = (str) => {
|
||||||
return /^[0-9]*$/.test(str);
|
return /^[0-9]*$/.test(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isMoney: ValidatorMoneyFunction = (str, zero) => {
|
export const isMoney: ValidatorMoneyFunction = (str, zero) => {
|
||||||
// zero为true包含零
|
// 金额,最多可以有两位小数 zero为true包含零
|
||||||
if (zero) {
|
if (zero) {
|
||||||
// 金额,最多可以有两位小数
|
return /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(
|
||||||
return /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(str);
|
str
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return /(^[1-9](\d+)?(\.\d{1,2})?$)|(^\d\.\d{1,2}$)/.test(str);
|
return /(^[1-9](\d+)?(\.\d{1,2})?$)|(^\d\.\d{1,2}$)/.test(str);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue