Merge branch 'release'
This commit is contained in:
commit
3d539b93db
|
|
@ -1123,7 +1123,8 @@ function constructFilter(statements, entity) {
|
|||
case 'Int':
|
||||
case 'Uint':
|
||||
case 'Float':
|
||||
case 'Double': {
|
||||
case 'Double':
|
||||
case 'Price': {
|
||||
type2 = factory.createTypeReferenceNode(factory.createIdentifier('Q_NumberValue'));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1276,7 +1277,8 @@ function constructProjection(statements, entity) {
|
|||
case 'File':
|
||||
case 'SingleGeo':
|
||||
case 'Geo':
|
||||
case 'Object': {
|
||||
case 'Object':
|
||||
case 'Price': {
|
||||
properties.push([name_4, false]);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1639,7 +1641,8 @@ function constructSorter(statements, entity) {
|
|||
case 'Boolean':
|
||||
case 'Datetime':
|
||||
case 'Image':
|
||||
case 'File': {
|
||||
case 'File':
|
||||
case 'Price': {
|
||||
type2 = factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
|
||||
break;
|
||||
}
|
||||
|
|
@ -2658,6 +2661,7 @@ var initialStatements = function () { return [
|
|||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Text')),
|
||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('Datetime')),
|
||||
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('PrimaryKey')),
|
||||
factory.createImportSpecifier(false, undefined, factory.createIdentifier('ForeignKey')),
|
||||
|
|
@ -2934,15 +2938,13 @@ function constructAttributes(entity) {
|
|||
], true)));
|
||||
break;
|
||||
}
|
||||
case 'Float': {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("float")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(typeArguments[0].literal.text)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(typeArguments[1].literal.text))
|
||||
], true)));
|
||||
break;
|
||||
}
|
||||
case 'Double': {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("double")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||
case 'Double':
|
||||
case 'Float':
|
||||
case 'Decimal': {
|
||||
if (['Double', 'Float'].includes(text)) {
|
||||
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"));
|
||||
}
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("decimal")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(typeArguments[0].literal.text)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(typeArguments[1].literal.text))
|
||||
], true)));
|
||||
|
|
@ -2952,6 +2954,10 @@ function constructAttributes(entity) {
|
|||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("boolean")));
|
||||
break;
|
||||
}
|
||||
case 'Price': {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("money")));
|
||||
break;
|
||||
}
|
||||
case 'Datetime': {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("datetime")));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ var indexes = [
|
|||
];
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
name: '更新',
|
||||
attr: {
|
||||
targetEntity: '目标对象',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ var config = {
|
|||
};
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
name: '更新对象连接',
|
||||
attr: {
|
||||
modi: '更新',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ var configuration = {
|
|||
};
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
name: '操作',
|
||||
attr: {
|
||||
action: '动作',
|
||||
data: '数据',
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ var config = {
|
|||
};
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
name: '操作对象连接',
|
||||
attr: {
|
||||
oper: '操作',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ var UserActionDef = {
|
|||
};
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
name: '用户',
|
||||
attr: {
|
||||
name: '姓名',
|
||||
nickname: '昵称',
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
;
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
name: '用户授权',
|
||||
attr: {
|
||||
relation: '关系',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -64,93 +64,91 @@ var AsyncContext = /** @class */ (function () {
|
|||
};
|
||||
AsyncContext.prototype.commit = function () {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var _a, _b, e, e_1_1;
|
||||
var e_1, _c;
|
||||
return tslib_1.__generator(this, function (_d) {
|
||||
switch (_d.label) {
|
||||
var commitEvents, commitEvents_1, commitEvents_1_1, e, e_1_1;
|
||||
var e_1, _a;
|
||||
return tslib_1.__generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
case 0:
|
||||
if (!this.uuid) return [3 /*break*/, 10];
|
||||
if (!this.uuid) return [3 /*break*/, 9];
|
||||
return [4 /*yield*/, this.rowStore.commit(this.uuid)];
|
||||
case 1:
|
||||
_d.sent();
|
||||
_b.sent();
|
||||
this.uuid = undefined;
|
||||
_d.label = 2;
|
||||
commitEvents = this.events.commit;
|
||||
this.resetEvents();
|
||||
_b.label = 2;
|
||||
case 2:
|
||||
_d.trys.push([2, 7, 8, 9]);
|
||||
_a = tslib_1.__values(this.events.commit), _b = _a.next();
|
||||
_d.label = 3;
|
||||
_b.trys.push([2, 7, 8, 9]);
|
||||
commitEvents_1 = tslib_1.__values(commitEvents), commitEvents_1_1 = commitEvents_1.next();
|
||||
_b.label = 3;
|
||||
case 3:
|
||||
if (!!_b.done) return [3 /*break*/, 6];
|
||||
e = _b.value;
|
||||
if (!!commitEvents_1_1.done) return [3 /*break*/, 6];
|
||||
e = commitEvents_1_1.value;
|
||||
return [4 /*yield*/, e()];
|
||||
case 4:
|
||||
_d.sent();
|
||||
_d.label = 5;
|
||||
_b.sent();
|
||||
_b.label = 5;
|
||||
case 5:
|
||||
_b = _a.next();
|
||||
commitEvents_1_1 = commitEvents_1.next();
|
||||
return [3 /*break*/, 3];
|
||||
case 6: return [3 /*break*/, 9];
|
||||
case 7:
|
||||
e_1_1 = _d.sent();
|
||||
e_1_1 = _b.sent();
|
||||
e_1 = { error: e_1_1 };
|
||||
return [3 /*break*/, 9];
|
||||
case 8:
|
||||
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; }
|
||||
return [7 /*endfinally*/];
|
||||
case 9:
|
||||
this.resetEvents();
|
||||
_d.label = 10;
|
||||
case 10: return [2 /*return*/];
|
||||
case 9: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
AsyncContext.prototype.rollback = function () {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var _a, _b, e, e_2_1;
|
||||
var e_2, _c;
|
||||
return tslib_1.__generator(this, function (_d) {
|
||||
switch (_d.label) {
|
||||
var rollbackEvents, rollbackEvents_1, rollbackEvents_1_1, e, e_2_1;
|
||||
var e_2, _a;
|
||||
return tslib_1.__generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
case 0:
|
||||
if (!this.uuid) return [3 /*break*/, 10];
|
||||
if (!this.uuid) return [3 /*break*/, 9];
|
||||
return [4 /*yield*/, this.rowStore.rollback(this.uuid)];
|
||||
case 1:
|
||||
_d.sent();
|
||||
_b.sent();
|
||||
// console.log('rollback', this.uuid);
|
||||
this.uuid = undefined;
|
||||
_d.label = 2;
|
||||
rollbackEvents = this.events.rollback;
|
||||
this.resetEvents();
|
||||
_b.label = 2;
|
||||
case 2:
|
||||
_d.trys.push([2, 7, 8, 9]);
|
||||
_a = tslib_1.__values(this.events.rollback), _b = _a.next();
|
||||
_d.label = 3;
|
||||
_b.trys.push([2, 7, 8, 9]);
|
||||
rollbackEvents_1 = tslib_1.__values(rollbackEvents), rollbackEvents_1_1 = rollbackEvents_1.next();
|
||||
_b.label = 3;
|
||||
case 3:
|
||||
if (!!_b.done) return [3 /*break*/, 6];
|
||||
e = _b.value;
|
||||
if (!!rollbackEvents_1_1.done) return [3 /*break*/, 6];
|
||||
e = rollbackEvents_1_1.value;
|
||||
return [4 /*yield*/, e()];
|
||||
case 4:
|
||||
_d.sent();
|
||||
_d.label = 5;
|
||||
_b.sent();
|
||||
_b.label = 5;
|
||||
case 5:
|
||||
_b = _a.next();
|
||||
rollbackEvents_1_1 = rollbackEvents_1.next();
|
||||
return [3 /*break*/, 3];
|
||||
case 6: return [3 /*break*/, 9];
|
||||
case 7:
|
||||
e_2_1 = _d.sent();
|
||||
e_2_1 = _b.sent();
|
||||
e_2 = { error: e_2_1 };
|
||||
return [3 /*break*/, 9];
|
||||
case 8:
|
||||
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; }
|
||||
return [7 /*endfinally*/];
|
||||
case 9:
|
||||
this.resetEvents();
|
||||
_d.label = 10;
|
||||
case 10: return [2 /*return*/];
|
||||
case 9: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -339,12 +339,18 @@ function translateCascadeRelationFilterMaker(schema, lch, entity2, pathPrefix) {
|
|||
};
|
||||
var filterMaker = paths.length ? translateFilterMakerIter(entity2, 0) : translateRelationFilter(entity2);
|
||||
if (!paths.length) {
|
||||
// 不可能是create
|
||||
return function (oper, userId) { return filterMaker(userId); };
|
||||
}
|
||||
/**
|
||||
* 针对第一层做一下特别优化,比如对象A指向对象B(多对一),如果A的cascadePath是 'B',
|
||||
* 当create A时,会带有Bid。此时生成该B对象上的相关表达式查询返回,可以避免必须将此判定在对象创建之后再做
|
||||
* 另一使用场景是,在查询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 relation = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
||||
|
|
@ -352,54 +358,129 @@ function translateCascadeRelationFilterMaker(schema, lch, entity2, pathPrefix) {
|
|||
var filterMaker2 = paths.length > 1
|
||||
? (relation === 2 ? translateFilterMakerIter(attr, 1) : translateFilterMakerIter(relation, 1))
|
||||
: (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) {
|
||||
var action = operation.action;
|
||||
if (action === 'create') {
|
||||
var data = operation.data;
|
||||
var getForeignKeyId_1 = function (d) {
|
||||
if (data) {
|
||||
// 有data的情形根据data判定
|
||||
var getForeignKeyId_1 = function (d) {
|
||||
if (relation === 2) {
|
||||
if (d.entity === attr && typeof d.entityId === 'string') {
|
||||
return d.entityId;
|
||||
}
|
||||
throw new Exception_1.OakUserUnpermittedException();
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(typeof relation === 'string');
|
||||
if (typeof d["".concat(attr, "Id")] === 'string') {
|
||||
return d["".concat(attr, "Id")];
|
||||
}
|
||||
throw new Exception_1.OakUserUnpermittedException();
|
||||
}
|
||||
};
|
||||
if (relation === 2) {
|
||||
if (d.entity === attr && typeof d.entityId === 'string') {
|
||||
return d.entitId;
|
||||
if (data instanceof Array) {
|
||||
var fkIds = (0, lodash_1.uniq)(data.map(function (d) { return getForeignKeyId_1(d); }));
|
||||
return {
|
||||
$entity: attr,
|
||||
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: { $in: fkIds } }),
|
||||
$count: fkIds.length,
|
||||
};
|
||||
}
|
||||
throw new Exception_1.OakUserUnpermittedException();
|
||||
var fkId_1 = getForeignKeyId_1(data);
|
||||
return {
|
||||
$entity: attr,
|
||||
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: fkId_1 }),
|
||||
};
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(typeof relation === 'string');
|
||||
if (typeof d["".concat(attr, "Id")] === 'string') {
|
||||
return d["".concat(attr, "Id")];
|
||||
}
|
||||
throw new Exception_1.OakUserUnpermittedException();
|
||||
}
|
||||
};
|
||||
if (relation === 2) {
|
||||
(0, assert_1.default)(typeof relation === 'string');
|
||||
if (data instanceof Array) {
|
||||
var fkIds = (0, lodash_1.uniq)(data.map(function (d) { return getForeignKeyId_1(d); }));
|
||||
return {
|
||||
$entity: attr,
|
||||
$entity: relation,
|
||||
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: { $in: fkIds } }),
|
||||
$count: fkIds.length,
|
||||
};
|
||||
}
|
||||
var fkId_1 = getForeignKeyId_1(data);
|
||||
return {
|
||||
$entity: attr,
|
||||
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: fkId_1 }),
|
||||
};
|
||||
}
|
||||
(0, assert_1.default)(typeof relation === 'string');
|
||||
if (data instanceof Array) {
|
||||
var fkIds = (0, lodash_1.uniq)(data.map(function (d) { return getForeignKeyId_1(d); }));
|
||||
var fkId = getForeignKeyId_1(data);
|
||||
return {
|
||||
$entity: relation,
|
||||
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: { $in: fkIds } }),
|
||||
$count: fkIds.length,
|
||||
$filter: (0, filter_1.addFilterSegment)(filterMaker2(userId), { id: fkId }),
|
||||
};
|
||||
}
|
||||
var fkId = getForeignKeyId_1(data);
|
||||
return {
|
||||
$entity: relation,
|
||||
$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;
|
||||
if (relation === 2 && (filter === null || filter === void 0 ? void 0 : filter.entity) === attr && (filter === null || filter === void 0 ? void 0 : filter.entityId)) {
|
||||
|
|
@ -450,8 +531,77 @@ function translateActionAuthFilterMaker(schema, relationItem, entity, pathPrefix
|
|||
var filterMaker = translateCascadeRelationFilterMaker(schema, relationItem, entity, pathPrefix);
|
||||
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) {
|
||||
var e_1, _a;
|
||||
var e_1, _a, e_2, _b;
|
||||
var userId = context.getCurrentUserId();
|
||||
(0, assert_1.default)(userId);
|
||||
var filters = filterMaker instanceof Array ? filterMaker.map(function (ele) {
|
||||
|
|
@ -470,103 +620,81 @@ function makePotentialFilter(operation, context, filterMaker) {
|
|||
*/
|
||||
var filtersOr = [];
|
||||
var isAsyncOr = false;
|
||||
var _loop_1 = function (f) {
|
||||
var e_2, _b;
|
||||
if (f instanceof Array) {
|
||||
var isAsyncAnd = true;
|
||||
var filtersAnd = [];
|
||||
var _loop_2 = function (ff) {
|
||||
if (ff === null || ff === void 0 ? void 0 : ff.$entity) {
|
||||
var _e = ff, $entity = _e.$entity, $filter = _e.$filter, _f = _e.$count, $count_1 = _f === void 0 ? 1 : _f;
|
||||
var count = context.count($entity, {
|
||||
filter: $filter,
|
||||
}, {});
|
||||
if (count instanceof Promise) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
else if (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 }; }
|
||||
finally {
|
||||
try {
|
||||
if (f_1_1 && !f_1_1.done && (_b = f_1.return)) _b.call(f_1);
|
||||
}
|
||||
finally { if (e_2) throw e_2.error; }
|
||||
}
|
||||
if (isAsyncAnd = true) {
|
||||
isAsyncOr = true;
|
||||
filtersOr.push(isAsyncAnd ? Promise.all(filtersAnd).then(function (fa) {
|
||||
var e_3, _a;
|
||||
var faR = [];
|
||||
try {
|
||||
for (var fa_1 = (e_3 = void 0, tslib_1.__values(fa)), fa_1_1 = fa_1.next(); !fa_1_1.done; fa_1_1 = fa_1.next()) {
|
||||
var faItem = fa_1_1.value;
|
||||
if (faItem instanceof Exception_1.OakUserUnpermittedException) {
|
||||
return faItem;
|
||||
}
|
||||
else if (faItem) {
|
||||
faR.push(faItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (fa_1_1 && !fa_1_1.done && (_a = fa_1.return)) _a.call(fa_1);
|
||||
}
|
||||
finally { if (e_3) throw e_3.error; }
|
||||
}
|
||||
if (faR.length > 0) {
|
||||
return {
|
||||
$and: faR,
|
||||
};
|
||||
}
|
||||
}) : {
|
||||
$and: filtersAnd,
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (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 count = context.count($entity, {
|
||||
filter: $filter,
|
||||
}, {});
|
||||
if (count instanceof Promise) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
else if (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);
|
||||
if (f instanceof Array) {
|
||||
var isAsyncAnd = false;
|
||||
(0, assert_1.default)(f.length > 0);
|
||||
var filtersAnd = [];
|
||||
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;
|
||||
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)) {
|
||||
// 每个counter都要满足才能过
|
||||
var result = execCreateCounter(context, ff);
|
||||
if (result instanceof Promise) {
|
||||
isAsyncAnd = true;
|
||||
}
|
||||
filtersAnd.push(result);
|
||||
}
|
||||
else if (ff) {
|
||||
filtersAnd.push(ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (f_1_1 && !f_1_1.done && (_b = f_1.return)) _b.call(f_1);
|
||||
}
|
||||
finally { if (e_2) throw e_2.error; }
|
||||
}
|
||||
if (isAsyncAnd = true) {
|
||||
isAsyncOr = true;
|
||||
filtersOr.push(isAsyncAnd ? Promise.all(filtersAnd).then(function (fa) {
|
||||
var e_3, _a;
|
||||
var faR = [];
|
||||
try {
|
||||
for (var fa_1 = (e_3 = void 0, tslib_1.__values(fa)), fa_1_1 = fa_1.next(); !fa_1_1.done; fa_1_1 = fa_1.next()) {
|
||||
var faItem = fa_1_1.value;
|
||||
if (faItem instanceof Exception_1.OakUserUnpermittedException) {
|
||||
return faItem;
|
||||
}
|
||||
else if (faItem) {
|
||||
faR.push(faItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (fa_1_1 && !fa_1_1.done && (_a = fa_1.return)) _a.call(fa_1);
|
||||
}
|
||||
finally { if (e_3) throw e_3.error; }
|
||||
}
|
||||
if (faR.length > 0) {
|
||||
return {
|
||||
$and: faR,
|
||||
};
|
||||
}
|
||||
}) : {
|
||||
$and: filtersAnd,
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
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 counterResults = execCreateCounter(context, f);
|
||||
if (counterResults instanceof Promise) {
|
||||
isAsyncOr = true;
|
||||
}
|
||||
filtersOr.push(counterResults);
|
||||
}
|
||||
else if (f) {
|
||||
filtersOr.push(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
|
|
@ -603,18 +731,30 @@ function makePotentialFilter(operation, context, filterMaker) {
|
|||
*/
|
||||
function createAuthCheckers(schema, authDict) {
|
||||
var checkers = [];
|
||||
var _loop_3 = function (entity) {
|
||||
var _loop_1 = function (entity) {
|
||||
var _a;
|
||||
if (authDict[entity]) {
|
||||
var _b = authDict[entity], relationAuth = _b.relationAuth, actionAuth = _b.actionAuth;
|
||||
if (relationAuth) {
|
||||
var raFilterMakerDict_1 = {};
|
||||
var userEntityName = "user".concat((0, string_1.firstLetterUpperCase)(entity));
|
||||
var allAuthItem = [];
|
||||
for (var r in relationAuth) {
|
||||
var authItem = relationAuth[r];
|
||||
Object.assign(raFilterMakerDict_1, (_a = {},
|
||||
_a[r] = translateActionAuthFilterMaker(schema, relationAuth[r], userEntityName, entity),
|
||||
_a[r] = translateActionAuthFilterMaker(schema, authItem, userEntityName, entity),
|
||||
_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");
|
||||
checkers.push({
|
||||
entity: userEntityName,
|
||||
|
|
@ -624,8 +764,12 @@ function createAuthCheckers(schema, authDict) {
|
|||
var data = operation.data;
|
||||
(0, assert_1.default)(!(data instanceof Array));
|
||||
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]) {
|
||||
return;
|
||||
throw new Exception_1.OakUserUnpermittedException();
|
||||
}
|
||||
var filter = makePotentialFilter(operation, context, raFilterMakerDict_1[relation]);
|
||||
return filter;
|
||||
|
|
@ -694,7 +838,7 @@ function createAuthCheckers(schema, authDict) {
|
|||
// todo 等实现的时候再写
|
||||
}
|
||||
if (actionAuth) {
|
||||
var _loop_4 = function (a) {
|
||||
var _loop_2 = function (a) {
|
||||
var filterMaker = translateActionAuthFilterMaker(schema, actionAuth[a], entity);
|
||||
checkers.push({
|
||||
entity: entity,
|
||||
|
|
@ -709,13 +853,13 @@ function createAuthCheckers(schema, authDict) {
|
|||
});
|
||||
};
|
||||
for (var a in actionAuth) {
|
||||
_loop_4(a);
|
||||
_loop_2(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
for (var entity in schema) {
|
||||
_loop_3(entity);
|
||||
_loop_1(entity);
|
||||
}
|
||||
return checkers;
|
||||
}
|
||||
|
|
@ -784,7 +928,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
}
|
||||
// 当删除一时,要确认多上面没有指向一的数据
|
||||
var entities = (0, lodash_1.union)(Object.keys(OneToManyMatrix), Object.keys(OneToManyOnEntityMatrix));
|
||||
var _loop_5 = function (entity) {
|
||||
var _loop_3 = function (entity) {
|
||||
checkers.push({
|
||||
entity: entity,
|
||||
action: 'remove',
|
||||
|
|
@ -793,7 +937,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
var e_6, _a, e_7, _b;
|
||||
var promises = [];
|
||||
if (OneToManyMatrix[entity]) {
|
||||
var _loop_7 = function (otm) {
|
||||
var _loop_5 = function (otm) {
|
||||
var _g, _h;
|
||||
var _j = tslib_1.__read(otm, 2), e = _j[0], attr = _j[1];
|
||||
var proj = (_g = {
|
||||
|
|
@ -832,7 +976,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
try {
|
||||
for (var _c = (e_6 = void 0, tslib_1.__values(OneToManyMatrix[entity])), _d = _c.next(); !_d.done; _d = _c.next()) {
|
||||
var otm = _d.value;
|
||||
_loop_7(otm);
|
||||
_loop_5(otm);
|
||||
}
|
||||
}
|
||||
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
||||
|
|
@ -844,7 +988,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
}
|
||||
}
|
||||
if (OneToManyOnEntityMatrix[entity]) {
|
||||
var _loop_8 = function (otm) {
|
||||
var _loop_6 = function (otm) {
|
||||
var _l, _m, _o;
|
||||
var proj = {
|
||||
id: 1,
|
||||
|
|
@ -890,7 +1034,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
try {
|
||||
for (var _e = (e_7 = void 0, tslib_1.__values(OneToManyOnEntityMatrix[entity])), _f = _e.next(); !_f.done; _f = _e.next()) {
|
||||
var otm = _f.value;
|
||||
_loop_8(otm);
|
||||
_loop_6(otm);
|
||||
}
|
||||
}
|
||||
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
||||
|
|
@ -910,7 +1054,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
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()) {
|
||||
var entity = entities_1_1.value;
|
||||
_loop_5(entity);
|
||||
_loop_3(entity);
|
||||
}
|
||||
}
|
||||
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; }
|
||||
}
|
||||
var _loop_6 = function (entity) {
|
||||
var _loop_4 = function (entity) {
|
||||
var e_8, _b;
|
||||
var cascadeRemove = authDict[entity].cascadeRemove;
|
||||
if (cascadeRemove) {
|
||||
var entitiesOnEntityAttr = [];
|
||||
var hasAllEntity = false;
|
||||
var _loop_9 = function (attr) {
|
||||
var _loop_7 = function (attr) {
|
||||
if (attr === '@entity') {
|
||||
hasAllEntity = true;
|
||||
return "continue";
|
||||
|
|
@ -1001,13 +1145,13 @@ function createRemoveCheckers(schema, authDict) {
|
|||
}
|
||||
};
|
||||
for (var attr in cascadeRemove) {
|
||||
_loop_9(attr);
|
||||
_loop_7(attr);
|
||||
}
|
||||
if (hasAllEntity) {
|
||||
var attributes = schema[entity].attributes;
|
||||
var ref = attributes.entity.ref;
|
||||
var restEntities = (0, lodash_1.difference)(ref, entitiesOnEntityAttr);
|
||||
var _loop_10 = function (e) {
|
||||
var _loop_8 = function (e) {
|
||||
checkers.push({
|
||||
entity: e,
|
||||
action: 'remove',
|
||||
|
|
@ -1043,7 +1187,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
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()) {
|
||||
var e = restEntities_1_1.value;
|
||||
_loop_10(e);
|
||||
_loop_8(e);
|
||||
}
|
||||
}
|
||||
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
||||
|
|
@ -1058,7 +1202,7 @@ function createRemoveCheckers(schema, authDict) {
|
|||
};
|
||||
// 注入声明的cascade删除时的外键处理动作
|
||||
for (var entity in authDict) {
|
||||
_loop_6(entity);
|
||||
_loop_4(entity);
|
||||
}
|
||||
return checkers;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,14 @@ export declare type Text = string;
|
|||
export declare type Image = string;
|
||||
export declare type File = string;
|
||||
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 Price = number;
|
||||
export declare type PrimaryKey = string;
|
||||
export declare type ForeignKey<E extends string> = string;
|
||||
export declare type Sequence = string;
|
||||
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 unIndexedTypes: string[];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
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'];
|
||||
|
|
|
|||
|
|
@ -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>> = {
|
||||
[L in Language]?: {
|
||||
name: string;
|
||||
attr: LocaleOfSchema<Sc> & {
|
||||
[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 { AsyncContext } from "../store/AsyncRowStore";
|
||||
import { AsyncContext } from '../store/AsyncRowStore';
|
||||
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>> = {
|
||||
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>> = {
|
||||
name: string;
|
||||
cron: string;
|
||||
cron: RecurrenceRule | RecurrenceSpecDateRange | RecurrenceSpecObjLit | Date | string | number;
|
||||
fn: RoutineFn<ED, Cxt>;
|
||||
};
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -19,3 +19,4 @@ export * from './Connector';
|
|||
export * from './Timer';
|
||||
export * from './Port';
|
||||
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("./Port"), exports);
|
||||
tslib_1.__exportStar(require("./Endpoint"), exports);
|
||||
tslib_1.__exportStar(require("./Style"), exports);
|
||||
|
|
|
|||
|
|
@ -29,4 +29,6 @@ export interface DataTypeParams {
|
|||
precision?: number;
|
||||
scale?: number;
|
||||
signed?: boolean;
|
||||
max?: number;
|
||||
min?: number;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ function makeContentTypeAndBody(data) {
|
|||
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
||||
if (data instanceof FormData) {
|
||||
return {
|
||||
contentType: 'multipart/form-data',
|
||||
// contentType: 'multipart/form-data',
|
||||
body: data,
|
||||
};
|
||||
}
|
||||
|
|
@ -39,11 +39,12 @@ var SimpleConnector = /** @class */ (function (_super) {
|
|||
_a = makeContentTypeAndBody(params), contentType = _a.contentType, body = _a.body;
|
||||
return [4 /*yield*/, global.fetch(this.serverUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': contentType,
|
||||
headers: Object.assign({
|
||||
'oak-cxt': cxtStr,
|
||||
'oak-aspect': name,
|
||||
},
|
||||
}, contentType && {
|
||||
'Content-Type': contentType,
|
||||
}),
|
||||
body: body,
|
||||
})];
|
||||
case 1:
|
||||
|
|
@ -106,7 +107,7 @@ var SimpleConnector = /** @class */ (function (_super) {
|
|||
});
|
||||
};
|
||||
SimpleConnector.prototype.serializeResult = function (result, context, headers, body) {
|
||||
if (result instanceof stream_1.Stream) {
|
||||
if (result instanceof stream_1.Stream || result instanceof Buffer) {
|
||||
return {
|
||||
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 isDigital: ValidatorFunction;
|
||||
export declare const isPhone: ValidatorFunction;
|
||||
export declare const isTel: ValidatorFunction;
|
||||
export declare const isNumber: ValidatorFunction;
|
||||
export declare const isMoney: ValidatorMoneyFunction;
|
||||
export declare const isVehicleNumber: ValidatorFunction;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
'use strict';
|
||||
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 isMobile = function (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);
|
||||
};
|
||||
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) {
|
||||
return /^[0-9]*$/.test(str);
|
||||
};
|
||||
exports.isNumber = isNumber;
|
||||
var isMoney = function (str, zero) {
|
||||
// zero为true包含零
|
||||
// 金额,最多可以有两位小数 zero为true包含零
|
||||
if (zero) {
|
||||
// 金额,最多可以有两位小数
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-domain",
|
||||
"version": "2.6.3",
|
||||
"version": "2.6.4",
|
||||
"author": {
|
||||
"name": "XuChang"
|
||||
},
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
"@types/luxon": "^2.0.9",
|
||||
"@types/mocha": "^8.2.0",
|
||||
"@types/node": "^14.14.25",
|
||||
"@types/node-schedule": "^2.1.0",
|
||||
"@types/react": "^17.0.2",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/wechat-miniprogram": "^3.4.1",
|
||||
|
|
@ -40,9 +41,9 @@
|
|||
"typescript": "^4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@datasert/cronjs-matcher": "^1.2.0",
|
||||
"dayjs": "^1.11.5",
|
||||
"lodash": "^4.17.21",
|
||||
"node-schedule": "^2.1.1",
|
||||
"uuid": "^9.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1642,7 +1642,8 @@ function constructFilter(statements: Array<ts.Statement>, entity: string) {
|
|||
case 'Int':
|
||||
case 'Uint':
|
||||
case 'Float':
|
||||
case 'Double': {
|
||||
case 'Double':
|
||||
case 'Price': {
|
||||
type2 = factory.createTypeReferenceNode(
|
||||
factory.createIdentifier('Q_NumberValue'),
|
||||
);
|
||||
|
|
@ -1897,7 +1898,8 @@ function constructProjection(statements: Array<ts.Statement>, entity: string) {
|
|||
case 'File':
|
||||
case 'SingleGeo':
|
||||
case 'Geo':
|
||||
case 'Object': {
|
||||
case 'Object':
|
||||
case 'Price': {
|
||||
properties.push(
|
||||
[name, false]
|
||||
)
|
||||
|
|
@ -2410,7 +2412,8 @@ function constructSorter(statements: Array<ts.Statement>, entity: string) {
|
|||
case 'Boolean':
|
||||
case 'Datetime':
|
||||
case 'Image':
|
||||
case 'File': {
|
||||
case 'File':
|
||||
case 'Price': {
|
||||
type2 = factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
|
||||
break;
|
||||
}
|
||||
|
|
@ -4417,6 +4420,11 @@ const initialStatements = () => [
|
|||
undefined,
|
||||
factory.createIdentifier('File')
|
||||
),
|
||||
factory.createImportSpecifier(
|
||||
false,
|
||||
undefined,
|
||||
factory.createIdentifier('Price')
|
||||
),
|
||||
factory.createImportSpecifier(
|
||||
false,
|
||||
undefined,
|
||||
|
|
@ -5332,40 +5340,16 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] {
|
|||
);
|
||||
break;
|
||||
}
|
||||
case 'Float': {
|
||||
case 'Double':
|
||||
case 'Float':
|
||||
case 'Decimal': {
|
||||
if (['Double', 'Float'].includes(text)) {
|
||||
console.warn(`${entity}对象中还有${text}类型定义,现在统一用Decimal进行存储`);
|
||||
}
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("float")
|
||||
),
|
||||
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(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("double")
|
||||
factory.createStringLiteral("decimal")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
|
|
@ -5399,6 +5383,15 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] {
|
|||
);
|
||||
break;
|
||||
}
|
||||
case 'Price': {
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("money")
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'Datetime': {
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ const locale: LocaleDef<Schema, Action, '', {
|
|||
iState: IState,
|
||||
}> = {
|
||||
zh_CN: {
|
||||
name: '更新',
|
||||
attr: {
|
||||
targetEntity: '目标对象',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const config: Configuration = {
|
|||
|
||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||
zh_CN: {
|
||||
name: '更新对象连接',
|
||||
attr: {
|
||||
modi: '更新',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const configuration: Configuration = {
|
|||
|
||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||
zh_CN: {
|
||||
name: '操作',
|
||||
attr: {
|
||||
action: '动作',
|
||||
data: '数据',
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const config: Configuration = {
|
|||
|
||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||
zh_CN: {
|
||||
name: '操作对象连接',
|
||||
attr: {
|
||||
oper: '操作',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ const locale: LocaleDef<Schema, Action, '', {
|
|||
userState: UserState;
|
||||
}> = {
|
||||
zh_CN: {
|
||||
name: '用户',
|
||||
attr: {
|
||||
name: '姓名',
|
||||
nickname: '昵称',
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const locale: LocaleDef<
|
|||
{}
|
||||
> = {
|
||||
zh_CN: {
|
||||
name: '用户授权',
|
||||
attr: {
|
||||
relation: '关系',
|
||||
entity: '关联对象',
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
setHeaders(headers: IncomingHttpHeaders) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
|
||||
getHeader(key: string): string | string[] | undefined {
|
||||
if (this.headers) {
|
||||
return this.headers[key];
|
||||
|
|
@ -43,13 +43,13 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
this.scene = scene;
|
||||
}
|
||||
|
||||
private resetEvents() {
|
||||
private resetEvents() {
|
||||
this.events = {
|
||||
commit: [],
|
||||
rollback: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
on(event: 'commit' | 'rollback', callback: () => Promise<void>): void {
|
||||
this.uuid && this.events[event].push(callback);
|
||||
}
|
||||
|
|
@ -70,24 +70,26 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
if (this.uuid) {
|
||||
await this.rowStore.commit(this.uuid!);
|
||||
this.uuid = undefined;
|
||||
for(const e of this.events.commit) {
|
||||
const { commit: commitEvents } = this.events;
|
||||
this.resetEvents();
|
||||
for (const e of commitEvents) {
|
||||
await e();
|
||||
}
|
||||
this.resetEvents();
|
||||
}
|
||||
}
|
||||
async rollback(): Promise<void> {
|
||||
if(this.uuid) {
|
||||
if (this.uuid) {
|
||||
await this.rowStore.rollback(this.uuid!);
|
||||
// console.log('rollback', this.uuid);
|
||||
this.uuid = undefined;
|
||||
for(const e of this.events.rollback) {
|
||||
const { rollback: rollbackEvents } = this.events;
|
||||
this.resetEvents();
|
||||
for (const e of rollbackEvents) {
|
||||
await e();
|
||||
}
|
||||
this.resetEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
operate<T extends keyof ED, OP extends OperateOption>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
|
|
@ -95,21 +97,21 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
) {
|
||||
return this.rowStore.operate(entity, operation, this, option);
|
||||
}
|
||||
select<T extends keyof ED, OP extends SelectOption> (
|
||||
select<T extends keyof ED, OP extends SelectOption>(
|
||||
entity: T,
|
||||
selection: ED[T]['Selection'],
|
||||
option: OP
|
||||
) {
|
||||
return this.rowStore.select(entity, selection, this, option);
|
||||
}
|
||||
aggregate<T extends keyof ED, OP extends SelectOption> (
|
||||
aggregate<T extends keyof ED, OP extends SelectOption>(
|
||||
entity: T,
|
||||
aggregation: ED[T]['Aggregation'],
|
||||
option: OP
|
||||
) {
|
||||
return this.rowStore.aggregate(entity, aggregation, this, option);
|
||||
}
|
||||
count<T extends keyof ED, OP extends SelectOption> (
|
||||
count<T extends keyof ED, OP extends SelectOption>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
option: OP
|
||||
|
|
@ -120,7 +122,7 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
mergeMultipleResults(toBeMerged: OperationResult<ED>[]) {
|
||||
return this.rowStore.mergeMultipleResults(toBeMerged);
|
||||
}
|
||||
|
||||
|
||||
getCurrentTxnId() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
|
@ -140,7 +142,7 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
abstract isRoot(): boolean;
|
||||
|
||||
abstract getCurrentUserId(allowUnloggedIn?: boolean): string | undefined;
|
||||
|
||||
|
||||
abstract toString(): string;
|
||||
|
||||
abstract allowUserUpdate(): boolean;
|
||||
|
|
@ -154,21 +156,21 @@ export interface AsyncRowStore<ED extends EntityDict, Cxt extends Context> exten
|
|||
option: OP
|
||||
): Promise<OperationResult<ED>>;
|
||||
|
||||
select<T extends keyof ED, OP extends SelectOption> (
|
||||
select<T extends keyof ED, OP extends SelectOption>(
|
||||
entity: T,
|
||||
selection: ED[T]['Selection'],
|
||||
context: Cxt,
|
||||
option: OP
|
||||
): Promise<Partial<ED[T]['Schema']>[]>;
|
||||
|
||||
aggregate<T extends keyof ED, OP extends SelectOption> (
|
||||
aggregate<T extends keyof ED, OP extends SelectOption>(
|
||||
entity: T,
|
||||
aggregation: ED[T]['Aggregation'],
|
||||
context: Cxt,
|
||||
option: OP
|
||||
): Promise<AggregationResult<ED[T]['Schema']>>;
|
||||
|
||||
count<T extends keyof ED, OP extends SelectOption> (
|
||||
count<T extends keyof ED, OP extends SelectOption>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
context: Cxt,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||
$filter?: ED[keyof ED]['Selection']['filter'];
|
||||
$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>(
|
||||
schema: StorageSchema<ED>,
|
||||
lch: CascadeRelationItem,
|
||||
|
|
@ -315,12 +325,18 @@ function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityD
|
|||
|
||||
const filterMaker = paths.length ? translateFilterMakerIter(entity2, 0) : translateRelationFilter(entity2);
|
||||
if (!paths.length) {
|
||||
// 不可能是create
|
||||
return (oper, userId) => filterMaker(userId);
|
||||
}
|
||||
/**
|
||||
* 针对第一层做一下特别优化,比如对象A指向对象B(多对一),如果A的cascadePath是 'B',
|
||||
* 当create A时,会带有Bid。此时生成该B对象上的相关表达式查询返回,可以避免必须将此判定在对象创建之后再做
|
||||
* 另一使用场景是,在查询A时,如果带有Bid(在对象跳一对多子对象场景下很常见),可以提前判定这个查询对某些用户一定返回空集
|
||||
*
|
||||
* 20230306:
|
||||
* 在前台的权限判断中,会将list上的filter当成内在的限制对create动作进行判断,此时有一种可能是,filter并不能直接判断出外键,但会限制外键的查询范围。
|
||||
* 例如,在jichuang项目中,就存在park/list上,平台的用户去访问时,其查询条件是{ system: { platformId: 1 }};而用户的关系落在system.platform.platformProvider上,
|
||||
* 此时如直接通过data上的外键判断就会失败,需要通过对filter上相应的语义解构,进行进一步的判断
|
||||
*/
|
||||
const [attr] = paths;
|
||||
const relation = judgeRelation(schema, entity2, attr);
|
||||
|
|
@ -328,54 +344,145 @@ function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityD
|
|||
const filterMaker2 = paths.length > 1
|
||||
? (relation === 2 ? translateFilterMakerIter(attr, 1) : translateFilterMakerIter(relation, 1))
|
||||
: (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) => {
|
||||
const { action } = operation as ED[keyof ED]['Operation'];
|
||||
if (action === 'create') {
|
||||
const { data } = operation as ED[keyof ED]['Create'];
|
||||
const getForeignKeyId = (d: ED[keyof ED]['CreateSingle']['data']) => {
|
||||
if (data) {
|
||||
// 有data的情形根据data判定
|
||||
const getForeignKeyId = (d: ED[keyof ED]['CreateSingle']['data']) => {
|
||||
if (relation === 2) {
|
||||
if (d.entity === attr && typeof d.entityId === 'string') {
|
||||
return d.entityId as string;
|
||||
}
|
||||
throw new OakUserUnpermittedException();
|
||||
}
|
||||
else {
|
||||
assert(typeof relation === 'string');
|
||||
if (typeof d[`${attr}Id`] === 'string') {
|
||||
return d[`${attr}Id`] as string;
|
||||
}
|
||||
throw new OakUserUnpermittedException();
|
||||
}
|
||||
};
|
||||
if (relation === 2) {
|
||||
if (d.entity === attr && typeof d.entityId === 'string') {
|
||||
return d.entitId as string;
|
||||
if (data instanceof Array) {
|
||||
const fkIds = uniq(data.map(d => getForeignKeyId(d)));
|
||||
return {
|
||||
$entity: attr,
|
||||
$filter: addFilterSegment(filterMaker2(userId), { id: { $in: fkIds } }),
|
||||
$count: fkIds.length,
|
||||
};
|
||||
}
|
||||
throw new OakUserUnpermittedException();
|
||||
const fkId = getForeignKeyId(data);
|
||||
return {
|
||||
$entity: attr,
|
||||
$filter: addFilterSegment(filterMaker2(userId), { id: fkId }),
|
||||
};
|
||||
}
|
||||
else {
|
||||
assert(typeof relation === 'string');
|
||||
if (typeof d[`${attr}Id`] === 'string') {
|
||||
return d[`${attr}Id`] as string;
|
||||
}
|
||||
throw new OakUserUnpermittedException();
|
||||
}
|
||||
};
|
||||
if (relation === 2) {
|
||||
assert(typeof relation === 'string');
|
||||
if (data instanceof Array) {
|
||||
const fkIds = uniq(data.map(d => getForeignKeyId(d)));
|
||||
return {
|
||||
$entity: attr,
|
||||
$entity: relation,
|
||||
$filter: addFilterSegment(filterMaker2(userId), { id: { $in: fkIds } }),
|
||||
$count: fkIds.length,
|
||||
};
|
||||
}
|
||||
const fkId = getForeignKeyId(data);
|
||||
return {
|
||||
$entity: attr,
|
||||
$entity: relation,
|
||||
$filter: addFilterSegment(filterMaker2(userId), { id: fkId }),
|
||||
};
|
||||
}
|
||||
assert(typeof relation === 'string');
|
||||
if (data instanceof Array) {
|
||||
const fkIds = uniq(data.map(d => getForeignKeyId(d)));
|
||||
return {
|
||||
$entity: relation,
|
||||
$filter: addFilterSegment(filterMaker2(userId), { id: { $in: fkIds } }),
|
||||
$count: fkIds.length,
|
||||
};
|
||||
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 fkId = getForeignKeyId(data);
|
||||
return {
|
||||
$entity: relation,
|
||||
$filter: addFilterSegment(filterMaker2(userId), { id: fkId }),
|
||||
};
|
||||
}
|
||||
const { filter } = operation;
|
||||
if (relation === 2 && filter?.entity === attr && filter?.entityId) {
|
||||
|
|
@ -437,7 +544,94 @@ function translateActionAuthFilterMaker<ED extends EntityDict & BaseEntityDict>(
|
|||
return filterMaker;
|
||||
}
|
||||
|
||||
function makePotentialFilter<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>> (
|
||||
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>>(
|
||||
operation: ED[keyof ED]['Operation'] | ED[keyof ED]['Selection'],
|
||||
context: Cxt,
|
||||
filterMaker: FilterMakeFn<ED> | (FilterMakeFn<ED> | FilterMakeFn<ED>[])[]): SyncOrAsync<ED[keyof ED]['Selection']['filter']> {
|
||||
|
|
@ -466,30 +660,17 @@ function makePotentialFilter<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
let isAsyncOr = false;
|
||||
for (const f of filters) {
|
||||
if (f instanceof Array) {
|
||||
let isAsyncAnd = true;
|
||||
let isAsyncAnd = false;
|
||||
assert(f.length > 0);
|
||||
const filtersAnd: (SyncOrAsync<ED[keyof ED]['Selection']['filter'] | OakUserUnpermittedException<ED>>)[] = [];
|
||||
for (const ff of f) {
|
||||
if (ff?.$entity) {
|
||||
const { $entity, $filter, $count = 1 } = ff!;
|
||||
const count = context.count($entity, {
|
||||
filter: $filter,
|
||||
}, {});
|
||||
if (count instanceof Promise) {
|
||||
if ((<CreateRelationMultipleCounter<ED>>ff)?.$$and || (<CreateRelationMultipleCounter<ED>>ff)?.$$or || (<CreateRelationSingleCounter<ED>>ff)?.$entity) {
|
||||
// 每个counter都要满足才能过
|
||||
const result = execCreateCounter<ED, Cxt>(context, ff as CreateRelationMultipleCounter<ED>);
|
||||
if (result instanceof Promise) {
|
||||
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) {
|
||||
filtersAnd.push(ff as ED[keyof ED]['Selection']['filter']);
|
||||
|
|
@ -520,22 +701,12 @@ function makePotentialFilter<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (f?.$entity) {
|
||||
const { $entity, $filter, $count = 1 } = f!;
|
||||
const count = context.count($entity, {
|
||||
filter: $filter,
|
||||
}, {});
|
||||
if (count instanceof Promise) {
|
||||
if ((<CreateRelationMultipleCounter<ED>>f)?.$$and || (<CreateRelationMultipleCounter<ED>>f)?.$$or || (<CreateRelationSingleCounter<ED>>f)?.$entity) {
|
||||
const counterResults = execCreateCounter<ED, Cxt>(context, f as CreateRelationCounter<ED>);
|
||||
if (counterResults instanceof Promise) {
|
||||
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) {
|
||||
filtersOr.push(f as ED[keyof ED]['Selection']['filter']);
|
||||
|
|
@ -584,11 +755,26 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
|||
if (relationAuth) {
|
||||
const raFilterMakerDict = {} as Record<string, FilterMakeFn<ED> | (FilterMakeFn<ED> | FilterMakeFn<ED>[])[]>;
|
||||
const userEntityName = `user${firstLetterUpperCase(entity)}`;
|
||||
const allAuthItem: (CascadeRelationItem | CascadeRelationItem[])[] = [];
|
||||
for (const r in relationAuth) {
|
||||
const authItem = relationAuth[r as NonNullable<ED[keyof ED]['Relation']>]!;
|
||||
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`;
|
||||
checkers.push({
|
||||
entity: userEntityName as keyof ED,
|
||||
|
|
@ -598,11 +784,15 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
|||
const { data } = operation as ED[keyof ED]['Create'];
|
||||
assert(!(data instanceof Array));
|
||||
const { relation, [entityIdAttr]: entityId } = data;
|
||||
if (!relation) {
|
||||
// 不指定relation测试是否有创建权限
|
||||
return makePotentialFilter(operation, context, raFilterMakerDict['@@all']);
|
||||
}
|
||||
if (!raFilterMakerDict[relation]) {
|
||||
return;
|
||||
throw new OakUserUnpermittedException();
|
||||
}
|
||||
const filter = makePotentialFilter(operation, context, raFilterMakerDict[relation]);
|
||||
|
||||
|
||||
return filter;
|
||||
},
|
||||
errMsg: '越权操作',
|
||||
|
|
|
|||
|
|
@ -9,13 +9,17 @@ export type Text = string;
|
|||
export type Image = string;
|
||||
export type File = string;
|
||||
export type Datetime = number | Date;
|
||||
export type Day = number | Date;
|
||||
export type Time = number | Date;
|
||||
export type Boolean = boolean;
|
||||
export type Price = number;
|
||||
export type PrimaryKey = string;
|
||||
export type ForeignKey<E extends string> = string;
|
||||
export type Sequence = string; // 自增长序列,为了让人阅读方便,为了支持分布式这里用string,底层实现可自定义
|
||||
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'];
|
||||
|
|
|
|||
|
|
@ -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>> = {
|
||||
[L in Language]?: {
|
||||
name: string;
|
||||
attr: LocaleOfSchema<Sc> & {
|
||||
[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 { 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>> = {
|
||||
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>> = {
|
||||
name: string;
|
||||
cron: string;
|
||||
cron: RecurrenceRule | RecurrenceSpecDateRange | RecurrenceSpecObjLit | Date | string | number;
|
||||
fn: RoutineFn<ED, Cxt>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,3 +19,4 @@ export * from './Connector';
|
|||
export * from './Timer';
|
||||
export * from './Port';
|
||||
export * from './Endpoint';
|
||||
export * from './Style';
|
||||
|
|
|
|||
|
|
@ -218,4 +218,6 @@ export interface DataTypeParams {
|
|||
precision?: number;
|
||||
scale?: number;
|
||||
signed?: boolean;
|
||||
max?: number;
|
||||
min?: number;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ function makeContentTypeAndBody(data: any) {
|
|||
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
||||
if (data instanceof FormData) {
|
||||
return {
|
||||
contentType: 'multipart/form-data',
|
||||
// contentType: 'multipart/form-data',
|
||||
body: data,
|
||||
};
|
||||
}
|
||||
|
|
@ -41,11 +41,15 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
|||
const { contentType, body } = makeContentTypeAndBody(params);
|
||||
const response = await global.fetch(this.serverUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': contentType,
|
||||
'oak-cxt': cxtStr,
|
||||
'oak-aspect': name as string,
|
||||
},
|
||||
headers: Object.assign(
|
||||
{
|
||||
'oak-cxt': cxtStr,
|
||||
'oak-aspect': name as string,
|
||||
},
|
||||
contentType && {
|
||||
'Content-Type': contentType as string,
|
||||
}
|
||||
) as RequestInit['headers'],
|
||||
body,
|
||||
});
|
||||
if (response.status > 299) {
|
||||
|
|
@ -61,7 +65,7 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
|||
result,
|
||||
opRecords,
|
||||
} = await response.json();
|
||||
|
||||
|
||||
if (exception) {
|
||||
throw this.makeException(exception);
|
||||
}
|
||||
|
|
@ -87,7 +91,7 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
|||
return SimpleConnector.ROUTER;
|
||||
}
|
||||
|
||||
async parseRequest(headers: IncomingHttpHeaders, body: any, store: AsyncRowStore<ED, BackCxt>): Promise<{ name: string; params: any; context: BackCxt; }> {
|
||||
async parseRequest(headers: IncomingHttpHeaders, body: any, store: AsyncRowStore<ED, BackCxt>): Promise<{ name: string; params: any; context: BackCxt; }> {
|
||||
const { 'oak-cxt': oakCxtStr, 'oak-aspect': aspectName } = headers;
|
||||
assert(typeof oakCxtStr === 'string' || oakCxtStr === undefined);
|
||||
assert(typeof aspectName === 'string');
|
||||
|
|
@ -99,9 +103,9 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
|||
context,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
body: result,
|
||||
};
|
||||
|
|
@ -117,7 +121,7 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
|||
};
|
||||
}
|
||||
|
||||
serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): { body: any; headers?: Record<string, any> | undefined; } {
|
||||
serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): { body: any; headers?: Record<string, any> | undefined; } {
|
||||
return {
|
||||
body: {
|
||||
exception: exception.toString(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
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) => {
|
||||
return /^[0-9]*$/.test(str);
|
||||
}
|
||||
|
||||
export const isMoney: ValidatorMoneyFunction = (str, zero) => {
|
||||
// zero为true包含零
|
||||
// 金额,最多可以有两位小数 zero为true包含零
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue