UNPKG

database-proxy

Version:

Through a set of access control rules configuration database access to realize the client directly access the database via HTTP.

113 lines (112 loc) 4.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DataHandler = void 0; const types_1 = require("../../types"); const security_1 = require("../../utils/security"); const constraint_1 = require("../../utils/constraint"); const console_1 = require("console"); const DataHandler = async function (config, context) { // 缺省时,直接通过 if (config === undefined) { return null; } const { data, merge, action } = context.params; if (!data) return 'data is undefined'; if (typeof data !== 'object') return 'data must be an object'; if (action === types_1.ActionType.ADD) { return await dealAddData(config, context); } if (action === types_1.ActionType.UPDATE && merge) { return await dealUpdateData(config, context); } if (action === types_1.ActionType.UPDATE && !merge) { return await dealAddData(config, context); } }; exports.DataHandler = DataHandler; /** * 处理 add data * @param config * @param context * @returns */ async function dealAddData(config, context) { const { data } = context.params; // data in add 不可有操作符 if (security_1.SecurityUtil.hasUpdateOperator(data)) { return 'data must not contain any operator'; } const input_fields = Object.keys(data); if (!input_fields.length) return 'data is empty'; // 数组代表只允许出现的字段 if (config instanceof Array) { const allow_fields = config; const error = security_1.SecurityUtil.isAllowedFields(input_fields, allow_fields); return error; } // 对象则逐一检查字段约束 if (typeof config === 'object') { const allow_fields = Object.keys(config); let error = security_1.SecurityUtil.isAllowedFields(input_fields, allow_fields); if (error) return error; const constraint = new constraint_1.Constraint(context, data); for (const field of allow_fields) { error = await constraint.constraintField(field, config[field]); if (error) return error; } return null; } return 'config error: config must be an array or object'; } /** * 处理 update data * @param config * @param context * @returns */ async function dealUpdateData(config, context) { var _a; const { data, merge } = context.params; (0, console_1.assert)(merge, 'merge should be true when perform updating'); const flatten = security_1.SecurityUtil.flattenData(data); const fields = Object.keys(flatten); if (!fields.length) return 'data is empty'; let allow_fields = []; // 更新时必须有更新操作符,如 $set $push $inc $mul 之类的操作符 if (!security_1.SecurityUtil.hasUpdateOperator(data)) { return 'data must contain operator while `merge` with true'; } // 数组代表只允许出现的字段 if (config instanceof Array) { allow_fields = config; const error = security_1.SecurityUtil.isAllowedFields(fields, allow_fields); return error; } // 对象则逐一检查字段约束 if (typeof config === 'object') { allow_fields = Object.keys(config); let error = security_1.SecurityUtil.isAllowedFields(fields, allow_fields); if (error) return error; // 只对 $set 数据做约束检查 const set_data = (_a = data.$set) !== null && _a !== void 0 ? _a : {}; // 更新时忽略 required 和 default 约束 const constraint = new constraint_1.Constraint(context, set_data, [ constraint_1.ConstraintTypes.REQUIRED, constraint_1.ConstraintTypes.DEFAULT, ]); for (const field of allow_fields) { error = await constraint.constraintField(field, config[field]); if (error) return error; } return null; } return 'config error: config must be an array or object'; }